<commit_before>/* Copyright 2015 The TensorFlow Authors. 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 "absl/base/internal/sysinfo.h"
#include "tensorflow/core/platform/cpu_info.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mem.h"
#include "tensorflow/core/platform/numa.h"
#include "tensorflow/core/platform/profile_utils/cpu_utils.h"
#include "tensorflow/core/platform/snappy.h"
#include "tensorflow/core/platform/types.h"

#if defined(__linux__) && !defined(__ANDROID__)
#include <sched.h>
#include <sys/sysinfo.h>
#else
#include <sys/syscall.h>
#endif

#if (__x86_64__ || __i386__)
#include <cpuid.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef TF_USE_SNAPPY
#include "snappy.h"
#endif
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || \
    defined(__HAIKU__)
#include <thread>
#endif

#if TENSORFLOW_USE_NUMA
#include "hwloc.h"  // from @hwloc
#endif

#if defined(__ANDROID__) && (defined(__i386__) || defined(__x86_64__))
#define TENSORFLOW_HAS_CXA_DEMANGLE 0
#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
    !defined(__mips__)
#define TENSORFLOW_HAS_CXA_DEMANGLE 1
#elif defined(__clang__) && !defined(_MSC_VER)
#define TENSORFLOW_HAS_CXA_DEMANGLE 1
#else
#define TENSORFLOW_HAS_CXA_DEMANGLE 0
#endif

#if TENSORFLOW_HAS_CXA_DEMANGLE
#include <cxxabi.h>
#endif

namespace tensorflow {
namespace port {

void InitMain(const char* usage, int* argc, char*** argv) {}

string Hostname() {
  char hostname[1024];
  gethostname(hostname, sizeof hostname);
  hostname[sizeof hostname - 1] = 0;
  return string(hostname);
}

string JobName() {
  const char* job_name_cs = std::getenv("TF_JOB_NAME");
  if (job_name_cs != nullptr) {
    return string(job_name_cs);
  }
  return "";
}

int64_t JobUid() { return -1; }

int NumSchedulableCPUs() {
#if defined(__linux__) && !defined(__ANDROID__)
  cpu_set_t cpuset;
  if (sched_getaffinity(0, sizeof(cpu_set_t), &cpuset) == 0) {
    return CPU_COUNT(&cpuset);
  }
  perror("sched_getaffinity");
#endif
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || \
    defined(__HAIKU__)
  unsigned int count = std::thread::hardware_concurrency();
  if (count > 0) return static_cast<int>(count);
#endif
  const int kDefaultCores = 4;  // Semi-conservative guess
  fprintf(stderr, "can't determine number of CPU cores: assuming %d\n",
          kDefaultCores);
  return kDefaultCores;
}

int MaxParallelism() { return NumSchedulableCPUs(); }

int MaxParallelism(int numa_node) {
  if (numa_node != port::kNUMANoAffinity) {
    // Assume that CPUs are equally distributed over available NUMA nodes.
    // This may not be true, but there isn't currently a better way of
    // determining the number of CPUs specific to the requested node.
    return NumSchedulableCPUs() / port::NUMANumNodes();
  }
  return NumSchedulableCPUs();
}

int NumTotalCPUs() {
  int count = absl::base_internal::NumCPUs();
  return (count <= 0) ? kUnknownCPU : count;
}

int GetCurrentCPU() {
#if defined(__EMSCRIPTEN__)
  return sched_getcpu();
#elif defined(__linux__) && !defined(__ANDROID__)
  return sched_getcpu();
  // Attempt to use cpuid on all other platforms.  If that fails, perform a
  // syscall.
#elif defined(__cpuid) && !defined(__APPLE__)
  // TODO(b/120919972): __cpuid returns invalid APIC ids on OS X.
  uint32_t eax = 0;
  uint32_t ebx = 0;
  uint32_t ecx = 0;
  uint32_t edx = 0;
  __cpuid(/*level=*/1, eax, ebx, ecx, edx);
  if ((edx & /*bit_APIC=*/(1 << 9)) != 0) {
    // EBX bits 24-31 are APIC ID
    return (ebx & 0xFF) >> 24;
  }
#elif defined(__NR_getcpu)
  unsigned int cpu;
  if (syscall(__NR_getcpu, &cpu, NULL, NULL) < 0) {
    return kUnknownCPU;
  } else {
    return static_cast<int>(cpu);
  }
#endif
  return kUnknownCPU;
}

int NumHyperthreadsPerCore() {
  static const int ht_per_core = tensorflow::port::CPUIDNumSMT();
  return (ht_per_core > 0) ? ht_per_core : 1;
}

#ifdef TENSORFLOW_USE_NUMA
namespace {
static hwloc_topology_t hwloc_topology_handle;

bool HaveHWLocTopology() {
  // One time initialization
  static bool init = []() {
    if (hwloc_topology_init(&hwloc_topology_handle)) {
      LOG(ERROR) << "Call to hwloc_topology_init() failed";
      return false;
    }
    if (hwloc_topology_load(hwloc_topology_handle)) {
      LOG(ERROR) << "Call to hwloc_topology_load() failed";
      return false;
    }
    return true;
  }();
  return init;
}

// Return the first hwloc object of the given type whose os_index
// matches 'index'.
hwloc_obj_t GetHWLocTypeIndex(hwloc_obj_type_t tp, int index) {
  hwloc_obj_t obj = nullptr;
  if (index >= 0) {
    while ((obj = hwloc_get_next_obj_by_type(hwloc_topology_handle, tp, obj)) !=
           nullptr) {
      if (obj->os_index == index) break;
    }
  }
  return obj;
}
}  // namespace
#endif  // TENSORFLOW_USE_NUMA

bool NUMAEnabled() { return (NUMANumNodes() > 1); }

int NUMANumNodes() {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    int num_numanodes =
        hwloc_get_nbobjs_by_type(hwloc_topology_handle, HWLOC_OBJ_NUMANODE);
    return std::max(1, num_numanodes);
  } else {
    return 1;
  }
#else
  return 1;
#endif  // TENSORFLOW_USE_NUMA
}

void NUMASetThreadNodeAffinity(int node) {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    // Find the corresponding NUMA node topology object.
    hwloc_obj_t obj = GetHWLocTypeIndex(HWLOC_OBJ_NUMANODE, node);
    if (obj) {
      hwloc_set_cpubind(hwloc_topology_handle, obj->cpuset,
                        HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT);
    } else {
      LOG(ERROR) << "Could not find hwloc NUMA node " << node;
    }
  }
#endif  // TENSORFLOW_USE_NUMA
}

int NUMAGetThreadNodeAffinity() {
  int node_index = kNUMANoAffinity;
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    hwloc_cpuset_t thread_cpuset = hwloc_bitmap_alloc();
    hwloc_get_cpubind(hwloc_topology_handle, thread_cpuset,
                      HWLOC_CPUBIND_THREAD);
    hwloc_obj_t obj = nullptr;
    // Return the first NUMA node whose cpuset is a (non-proper) superset of
    // that of the current thread.
    while ((obj = hwloc_get_next_obj_by_type(
                hwloc_topology_handle, HWLOC_OBJ_NUMANODE, obj)) != nullptr) {
      if (hwloc_bitmap_isincluded(thread_cpuset, obj->cpuset)) {
        node_index = obj->os_index;
        break;
      }
    }
    hwloc_bitmap_free(thread_cpuset);
  }
#endif  // TENSORFLOW_USE_NUMA
  return node_index;
}

void* AlignedMalloc(size_t size, int minimum_alignment) {
#if defined(__ANDROID__)
  return memalign(minimum_alignment, size);
#else  // !defined(__ANDROID__)
  void* ptr = nullptr;
  // posix_memalign requires that the requested alignment be at least
  // sizeof(void*). In this case, fall back on malloc which should return
  // memory aligned to at least the size of a pointer.
  const int required_alignment = sizeof(void*);
  if (minimum_alignment < required_alignment) return Malloc(size);
  int err = posix_memalign(&ptr, minimum_alignment, size);
  if (err != 0) {
    return nullptr;
  } else {
    return ptr;
  }
#endif
}

void AlignedFree(void* aligned_memory) { Free(aligned_memory); }

void* Malloc(size_t size) { return malloc(size); }

void* Realloc(void* ptr, size_t size) { return realloc(ptr, size); }

void Free(void* ptr) { free(ptr); }

void* NUMAMalloc(int node, size_t size, int minimum_alignment) {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    hwloc_obj_t numa_node = GetHWLocTypeIndex(HWLOC_OBJ_NUMANODE, node);
    if (numa_node) {
      return hwloc_alloc_membind(hwloc_topology_handle, size,
                                 numa_node->nodeset, HWLOC_MEMBIND_BIND,
                                 HWLOC_MEMBIND_BYNODESET);
    } else {
      LOG(ERROR) << "Failed to find hwloc NUMA node " << node;
    }
  }
#endif  // TENSORFLOW_USE_NUMA
  return AlignedMalloc(size, minimum_alignment);
}

void NUMAFree(void* ptr, size_t size) {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    hwloc_free(hwloc_topology_handle, ptr, size);
    return;
  }
#endif  // TENSORFLOW_USE_NUMA
  Free(ptr);
}

int NUMAGetMemAffinity(const void* addr) {
  int node = kNUMANoAffinity;
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology() && addr) {
    hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
    if (!hwloc_get_area_memlocation(hwloc_topology_handle, addr, 4, nodeset,
                                    HWLOC_MEMBIND_BYNODESET)) {
      hwloc_obj_t obj = nullptr;
      while ((obj = hwloc_get_next_obj_by_type(
                  hwloc_topology_handle, HWLOC_OBJ_NUMANODE, obj)) != nullptr) {
        if (hwloc_bitmap_isincluded(nodeset, obj->nodeset)) {
          node = obj->os_index;
          break;
        }
      }
      hwloc_bitmap_free(nodeset);
    } else {
      LOG(ERROR) << "Failed call to hwloc_get_area_memlocation.";
    }
  }
#endif  // TENSORFLOW_USE_NUMA
  return node;
}

void MallocExtension_ReleaseToSystem(std::size_t num_bytes) {
  // No-op.
}

std::size_t MallocExtension_GetAllocatedSize(const void* p) {
#if !defined(__ANDROID__)
  return 0;
#else
  return malloc_usable_size(p);
#endif
}

bool Snappy_Compress(const char* input, size_t length, string* output) {
#ifdef TF_USE_SNAPPY
  output->resize(snappy::MaxCompressedLength(length));
  size_t outlen;
  snappy::RawCompress(input, length, &(*output)[0], &outlen);
  output->resize(outlen);
  return true;
#else
  return false;
#endif
}

bool Snappy_GetUncompressedLength(const char* input, size_t length,
                                  size_t* result) {
#ifdef TF_USE_SNAPPY
  return snappy::GetUncompressedLength(input, length, result);
#else
  return false;
#endif
}

bool Snappy_Uncompress(const char* input, size_t length, char* output) {
#ifdef TF_USE_SNAPPY
  return snappy::RawUncompress(input, length, output);
#else
  return false;
#endif
}

bool Snappy_UncompressToIOVec(const char* compressed, size_t compressed_length,
                              const struct iovec* iov, size_t iov_cnt) {
#ifdef TF_USE_SNAPPY
  return snappy::RawUncompressToIOVec(compressed, compressed_length, iov,
                                      iov_cnt);
#else
  return false;
#endif
}

static void DemangleToString(const char* mangled, string* out) {
  int status = 0;
  char* demangled = nullptr;
#if TENSORFLOW_HAS_CXA_DEMANGLE
  demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);
#endif
  if (status == 0 && demangled != nullptr) {  // Demangling succeeded.
    out->append(demangled);
    free(demangled);
  } else {
    out->append(mangled);
  }
}

string Demangle(const char* mangled) {
  string demangled;
  DemangleToString(mangled, &demangled);
  return demangled;
}

double NominalCPUFrequency() {
  return tensorflow::profile_utils::CpuUtils::GetCycleCounterFrequency();
}

MemoryInfo GetMemoryInfo() {
  MemoryInfo mem_info = {INT64_MAX, INT64_MAX};
#if defined(__linux__) && !defined(__ANDROID__)
  struct sysinfo info;
  int err = sysinfo(&info);
  if (err == 0) {
    mem_info.free = info.freeram;
    mem_info.total = info.totalram;
  }
#endif
  return mem_info;
}

MemoryBandwidthInfo GetMemoryBandwidthInfo() {
  MemoryBandwidthInfo membw_info = {INT64_MAX};
  return membw_info;
}

}  // namespace port
}  // namespace tensorflow
<commit_msg>Enhance NumSchedulableCPUs to allow for nodes with more than 1024 cores<commit_after>/* Copyright 2015 The TensorFlow Authors. 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 "absl/base/internal/sysinfo.h"
#include "tensorflow/core/platform/cpu_info.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mem.h"
#include "tensorflow/core/platform/numa.h"
#include "tensorflow/core/platform/profile_utils/cpu_utils.h"
#include "tensorflow/core/platform/snappy.h"
#include "tensorflow/core/platform/types.h"

#if defined(__linux__) && !defined(__ANDROID__)
#include <sched.h>
#include <sys/sysinfo.h>
#else
#include <sys/syscall.h>
#endif

#if (__x86_64__ || __i386__)
#include <cpuid.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef TF_USE_SNAPPY
#include "snappy.h"
#endif
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || \
    defined(__HAIKU__)
#include <thread>
#endif

#if TENSORFLOW_USE_NUMA
#include "hwloc.h"  // from @hwloc
#endif

#if defined(__ANDROID__) && (defined(__i386__) || defined(__x86_64__))
#define TENSORFLOW_HAS_CXA_DEMANGLE 0
#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
    !defined(__mips__)
#define TENSORFLOW_HAS_CXA_DEMANGLE 1
#elif defined(__clang__) && !defined(_MSC_VER)
#define TENSORFLOW_HAS_CXA_DEMANGLE 1
#else
#define TENSORFLOW_HAS_CXA_DEMANGLE 0
#endif

#if TENSORFLOW_HAS_CXA_DEMANGLE
#include <cxxabi.h>
#endif

namespace tensorflow {
namespace port {

void InitMain(const char* usage, int* argc, char*** argv) {}

string Hostname() {
  char hostname[1024];
  gethostname(hostname, sizeof hostname);
  hostname[sizeof hostname - 1] = 0;
  return string(hostname);
}

string JobName() {
  const char* job_name_cs = std::getenv("TF_JOB_NAME");
  if (job_name_cs != nullptr) {
    return string(job_name_cs);
  }
  return "";
}

int64_t JobUid() { return -1; }

int NumSchedulableCPUs() {
#if defined(__linux__) && !defined(__ANDROID__)
  for(int ncpus = 1024; ncpus < std::numeric_limits<int>::max() / 2; ncpus *= 2) {
    size_t setsize = CPU_ALLOC_SIZE(ncpus);
    cpu_set_t* mask = CPU_ALLOC(ncpus);
    if (!mask)
      break;
    if (sched_getaffinity(0, setsize, mask) == 0) {
      int result = CPU_COUNT_S(setsize, mask);
      CPU_FREE(mask);
      return result;
    }
    CPU_FREE(mask);
    if (errno != EINVAL)
      break;
  }
  perror("sched_getaffinity");
#endif
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) || \
    defined(__HAIKU__)
  unsigned int count = std::thread::hardware_concurrency();
  if (count > 0) return static_cast<int>(count);
#endif
  const int kDefaultCores = 4;  // Semi-conservative guess
  fprintf(stderr, "can't determine number of CPU cores: assuming %d\n",
          kDefaultCores);
  return kDefaultCores;
}

int MaxParallelism() { return NumSchedulableCPUs(); }

int MaxParallelism(int numa_node) {
  if (numa_node != port::kNUMANoAffinity) {
    // Assume that CPUs are equally distributed over available NUMA nodes.
    // This may not be true, but there isn't currently a better way of
    // determining the number of CPUs specific to the requested node.
    return NumSchedulableCPUs() / port::NUMANumNodes();
  }
  return NumSchedulableCPUs();
}

int NumTotalCPUs() {
  int count = absl::base_internal::NumCPUs();
  return (count <= 0) ? kUnknownCPU : count;
}

int GetCurrentCPU() {
#if defined(__EMSCRIPTEN__)
  return sched_getcpu();
#elif defined(__linux__) && !defined(__ANDROID__)
  return sched_getcpu();
  // Attempt to use cpuid on all other platforms.  If that fails, perform a
  // syscall.
#elif defined(__cpuid) && !defined(__APPLE__)
  // TODO(b/120919972): __cpuid returns invalid APIC ids on OS X.
  uint32_t eax = 0;
  uint32_t ebx = 0;
  uint32_t ecx = 0;
  uint32_t edx = 0;
  __cpuid(/*level=*/1, eax, ebx, ecx, edx);
  if ((edx & /*bit_APIC=*/(1 << 9)) != 0) {
    // EBX bits 24-31 are APIC ID
    return (ebx & 0xFF) >> 24;
  }
#elif defined(__NR_getcpu)
  unsigned int cpu;
  if (syscall(__NR_getcpu, &cpu, NULL, NULL) < 0) {
    return kUnknownCPU;
  } else {
    return static_cast<int>(cpu);
  }
#endif
  return kUnknownCPU;
}

int NumHyperthreadsPerCore() {
  static const int ht_per_core = tensorflow::port::CPUIDNumSMT();
  return (ht_per_core > 0) ? ht_per_core : 1;
}

#ifdef TENSORFLOW_USE_NUMA
namespace {
static hwloc_topology_t hwloc_topology_handle;

bool HaveHWLocTopology() {
  // One time initialization
  static bool init = []() {
    if (hwloc_topology_init(&hwloc_topology_handle)) {
      LOG(ERROR) << "Call to hwloc_topology_init() failed";
      return false;
    }
    if (hwloc_topology_load(hwloc_topology_handle)) {
      LOG(ERROR) << "Call to hwloc_topology_load() failed";
      return false;
    }
    return true;
  }();
  return init;
}

// Return the first hwloc object of the given type whose os_index
// matches 'index'.
hwloc_obj_t GetHWLocTypeIndex(hwloc_obj_type_t tp, int index) {
  hwloc_obj_t obj = nullptr;
  if (index >= 0) {
    while ((obj = hwloc_get_next_obj_by_type(hwloc_topology_handle, tp, obj)) !=
           nullptr) {
      if (obj->os_index == index) break;
    }
  }
  return obj;
}
}  // namespace
#endif  // TENSORFLOW_USE_NUMA

bool NUMAEnabled() { return (NUMANumNodes() > 1); }

int NUMANumNodes() {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    int num_numanodes =
        hwloc_get_nbobjs_by_type(hwloc_topology_handle, HWLOC_OBJ_NUMANODE);
    return std::max(1, num_numanodes);
  } else {
    return 1;
  }
#else
  return 1;
#endif  // TENSORFLOW_USE_NUMA
}

void NUMASetThreadNodeAffinity(int node) {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    // Find the corresponding NUMA node topology object.
    hwloc_obj_t obj = GetHWLocTypeIndex(HWLOC_OBJ_NUMANODE, node);
    if (obj) {
      hwloc_set_cpubind(hwloc_topology_handle, obj->cpuset,
                        HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT);
    } else {
      LOG(ERROR) << "Could not find hwloc NUMA node " << node;
    }
  }
#endif  // TENSORFLOW_USE_NUMA
}

int NUMAGetThreadNodeAffinity() {
  int node_index = kNUMANoAffinity;
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    hwloc_cpuset_t thread_cpuset = hwloc_bitmap_alloc();
    hwloc_get_cpubind(hwloc_topology_handle, thread_cpuset,
                      HWLOC_CPUBIND_THREAD);
    hwloc_obj_t obj = nullptr;
    // Return the first NUMA node whose cpuset is a (non-proper) superset of
    // that of the current thread.
    while ((obj = hwloc_get_next_obj_by_type(
                hwloc_topology_handle, HWLOC_OBJ_NUMANODE, obj)) != nullptr) {
      if (hwloc_bitmap_isincluded(thread_cpuset, obj->cpuset)) {
        node_index = obj->os_index;
        break;
      }
    }
    hwloc_bitmap_free(thread_cpuset);
  }
#endif  // TENSORFLOW_USE_NUMA
  return node_index;
}

void* AlignedMalloc(size_t size, int minimum_alignment) {
#if defined(__ANDROID__)
  return memalign(minimum_alignment, size);
#else  // !defined(__ANDROID__)
  void* ptr = nullptr;
  // posix_memalign requires that the requested alignment be at least
  // sizeof(void*). In this case, fall back on malloc which should return
  // memory aligned to at least the size of a pointer.
  const int required_alignment = sizeof(void*);
  if (minimum_alignment < required_alignment) return Malloc(size);
  int err = posix_memalign(&ptr, minimum_alignment, size);
  if (err != 0) {
    return nullptr;
  } else {
    return ptr;
  }
#endif
}

void AlignedFree(void* aligned_memory) { Free(aligned_memory); }

void* Malloc(size_t size) { return malloc(size); }

void* Realloc(void* ptr, size_t size) { return realloc(ptr, size); }

void Free(void* ptr) { free(ptr); }

void* NUMAMalloc(int node, size_t size, int minimum_alignment) {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    hwloc_obj_t numa_node = GetHWLocTypeIndex(HWLOC_OBJ_NUMANODE, node);
    if (numa_node) {
      return hwloc_alloc_membind(hwloc_topology_handle, size,
                                 numa_node->nodeset, HWLOC_MEMBIND_BIND,
                                 HWLOC_MEMBIND_BYNODESET);
    } else {
      LOG(ERROR) << "Failed to find hwloc NUMA node " << node;
    }
  }
#endif  // TENSORFLOW_USE_NUMA
  return AlignedMalloc(size, minimum_alignment);
}

void NUMAFree(void* ptr, size_t size) {
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology()) {
    hwloc_free(hwloc_topology_handle, ptr, size);
    return;
  }
#endif  // TENSORFLOW_USE_NUMA
  Free(ptr);
}

int NUMAGetMemAffinity(const void* addr) {
  int node = kNUMANoAffinity;
#ifdef TENSORFLOW_USE_NUMA
  if (HaveHWLocTopology() && addr) {
    hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
    if (!hwloc_get_area_memlocation(hwloc_topology_handle, addr, 4, nodeset,
                                    HWLOC_MEMBIND_BYNODESET)) {
      hwloc_obj_t obj = nullptr;
      while ((obj = hwloc_get_next_obj_by_type(
                  hwloc_topology_handle, HWLOC_OBJ_NUMANODE, obj)) != nullptr) {
        if (hwloc_bitmap_isincluded(nodeset, obj->nodeset)) {
          node = obj->os_index;
          break;
        }
      }
      hwloc_bitmap_free(nodeset);
    } else {
      LOG(ERROR) << "Failed call to hwloc_get_area_memlocation.";
    }
  }
#endif  // TENSORFLOW_USE_NUMA
  return node;
}

void MallocExtension_ReleaseToSystem(std::size_t num_bytes) {
  // No-op.
}

std::size_t MallocExtension_GetAllocatedSize(const void* p) {
#if !defined(__ANDROID__)
  return 0;
#else
  return malloc_usable_size(p);
#endif
}

bool Snappy_Compress(const char* input, size_t length, string* output) {
#ifdef TF_USE_SNAPPY
  output->resize(snappy::MaxCompressedLength(length));
  size_t outlen;
  snappy::RawCompress(input, length, &(*output)[0], &outlen);
  output->resize(outlen);
  return true;
#else
  return false;
#endif
}

bool Snappy_GetUncompressedLength(const char* input, size_t length,
                                  size_t* result) {
#ifdef TF_USE_SNAPPY
  return snappy::GetUncompressedLength(input, length, result);
#else
  return false;
#endif
}

bool Snappy_Uncompress(const char* input, size_t length, char* output) {
#ifdef TF_USE_SNAPPY
  return snappy::RawUncompress(input, length, output);
#else
  return false;
#endif
}

bool Snappy_UncompressToIOVec(const char* compressed, size_t compressed_length,
                              const struct iovec* iov, size_t iov_cnt) {
#ifdef TF_USE_SNAPPY
  return snappy::RawUncompressToIOVec(compressed, compressed_length, iov,
                                      iov_cnt);
#else
  return false;
#endif
}

static void DemangleToString(const char* mangled, string* out) {
  int status = 0;
  char* demangled = nullptr;
#if TENSORFLOW_HAS_CXA_DEMANGLE
  demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);
#endif
  if (status == 0 && demangled != nullptr) {  // Demangling succeeded.
    out->append(demangled);
    free(demangled);
  } else {
    out->append(mangled);
  }
}

string Demangle(const char* mangled) {
  string demangled;
  DemangleToString(mangled, &demangled);
  return demangled;
}

double NominalCPUFrequency() {
  return tensorflow::profile_utils::CpuUtils::GetCycleCounterFrequency();
}

MemoryInfo GetMemoryInfo() {
  MemoryInfo mem_info = {INT64_MAX, INT64_MAX};
#if defined(__linux__) && !defined(__ANDROID__)
  struct sysinfo info;
  int err = sysinfo(&info);
  if (err == 0) {
    mem_info.free = info.freeram;
    mem_info.total = info.totalram;
  }
#endif
  return mem_info;
}

MemoryBandwidthInfo GetMemoryBandwidthInfo() {
  MemoryBandwidthInfo membw_info = {INT64_MAX};
  return membw_info;
}

}  // namespace port
}  // namespace tensorflow
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s

// CHECK: DW_TAG_subrange_type

struct StructName {
  int member[];
};

struct StructName SN;
<commit_msg>Check that we have an unknown upper bound range for our flexible array members.<commit_after>// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s

// CHECK: metadata !{i32 {{.*}}, i64 1, i64 0}        ; [ DW_TAG_subrange_type ]

struct StructName {
  int member[];
};

struct StructName SN;
<|endoftext|>


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

#ifndef _STGCACHE_HXX
#define _STGCACHE_HXX

#ifndef _OSL_ENDIAN_H_
#include <osl/endian.h>
#endif
#ifndef _TOOLS_SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _TOOLS_STREAM_HXX
#include <tools/stream.hxx>
#endif

#ifndef _STGELEM_HXX
#include <stgelem.hxx>
#endif

class UCBStorageStream;

class StgIo;
class StgPage;
class StgDirEntry;
class StorageBase;

class StgCache {
    StgPage* pCur;                          // top of LRU list
    StgPage* pElem1;                        // top of ordered list
    ULONG nError;                           // error code
    INT32 nPages;                           // size of data area in pages
    USHORT nRef;                            // reference count
    void * pLRUCache;                       // hash table of cached objects
    short nPageSize;                        // page size of the file
    UCBStorageStream* pStorageStream;       // holds reference to UCB storage stream

    void Erase( StgPage* );                 // delete a cache element
    void InsertToLRU( StgPage* );           // insert into LRU list
    void InsertToOrdered( StgPage* );       // insert into ordered list
    StgPage* Create( INT32 );               // create a cached page
protected:
    SvStream* pStrm;                        // physical stream
    BOOL  bMyStream;                        // TRUE: delete stream in dtor
    BOOL  bFile;                            // TRUE: file stream
    INT32 Page2Pos( INT32 );                // page address --> file position
    INT32 Pos2Page( INT32 );                // file position --> page address
public:
    StgCache();
    ~StgCache();
    void  IncRef()                      { nRef++;           }
    USHORT DecRef()                     { return --nRef;    }
    void  SetPhysPageSize( short );
    INT32 GetPhysPages()                { return nPages;    }
    short GetPhysPageSize()             { return nPageSize; }
    SvStream* GetStrm()                 { return pStrm;     }
    void  SetStrm( SvStream*, BOOL );
    void  SetStrm( UCBStorageStream* );
    BOOL  IsWritable()                  { return pStrm->IsWritable(); }
    BOOL  Good()                        { return BOOL( nError == SVSTREAM_OK ); }
    BOOL  Bad()                         { return BOOL( nError != SVSTREAM_OK ); }
    ULONG GetError()                    { return nError;    }
    void  MoveError( StorageBase& );
    void  SetError( ULONG );
    void  ResetError();
    BOOL  Open( const String& rName, StreamMode );
    void  Close();
    BOOL  Read( INT32 nPage, void* pBuf, INT32 nPages );
    BOOL  Write( INT32 nPage, void* pBuf, INT32 nPages );
    BOOL  SetSize( INT32 nPages );
    StgPage* Find( INT32 );                 // find a cached page
    StgPage* Get( INT32, BOOL );            // get a cached page
    StgPage* Copy( INT32, INT32=STG_FREE ); // copy a page
    BOOL Commit( StgDirEntry* = NULL );     // flush all pages
    void Revert( StgDirEntry* = NULL );     // revert dirty pages
    void Clear();                           // clear the cache
};

class StgPage {
    friend class StgCache;
    StgCache* pCache;                       // the cache
    StgPage *pNext1, *pLast1;               // LRU chain
    StgPage *pNext2, *pLast2;               // ordered chain
    StgDirEntry* pOwner;                    // owner
    INT32   nPage;                          // page #
    BYTE*   pData;                          // nPageSize characters
    short   nData;                          // size of this page
    BOOL    bDirty;                         // dirty flag
    StgPage( StgCache*, short );
    ~StgPage();
public:
    void  SetDirty()                    { bDirty = TRUE;            }
    INT32 GetPage()                     { return nPage;             }
    void* GetData()                     { return pData;             }
    short GetSize()                     { return nData;             }
    void  SetOwner( StgDirEntry* p )    { pOwner = p;               }
    // routines for accessing FAT pages
    // Assume that the data is a FAT page and get/put FAT data.
    INT32 GetPage( short nOff )
    {
        if( ( nOff >= (short) ( nData / sizeof( INT32 ) ) ) || nOff < 0 )
            return -1;
        INT32 n = ((INT32*) pData )[ nOff ];
#ifdef OSL_BIGENDIAN
        return SWAPLONG(n);
#else
        return n;
#endif
    }
    void  SetPage( short, INT32 );      // put an element
};

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

#ifndef _STGCACHE_HXX
#define _STGCACHE_HXX

#include <osl/endian.h>
#ifndef _TOOLS_SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _TOOLS_STREAM_HXX
#include <tools/stream.hxx>
#endif
#include <stgelem.hxx>

class UCBStorageStream;

class StgIo;
class StgPage;
class StgDirEntry;
class StorageBase;

class StgCache {
    StgPage* pCur;                          // top of LRU list
    StgPage* pElem1;                        // top of ordered list
    ULONG nError;                           // error code
    INT32 nPages;                           // size of data area in pages
    USHORT nRef;                            // reference count
    void * pLRUCache;                       // hash table of cached objects
    short nPageSize;                        // page size of the file
    UCBStorageStream* pStorageStream;       // holds reference to UCB storage stream

    void Erase( StgPage* );                 // delete a cache element
    void InsertToLRU( StgPage* );           // insert into LRU list
    void InsertToOrdered( StgPage* );       // insert into ordered list
    StgPage* Create( INT32 );               // create a cached page
protected:
    SvStream* pStrm;                        // physical stream
    BOOL  bMyStream;                        // TRUE: delete stream in dtor
    BOOL  bFile;                            // TRUE: file stream
    INT32 Page2Pos( INT32 );                // page address --> file position
    INT32 Pos2Page( INT32 );                // file position --> page address
public:
    StgCache();
    ~StgCache();
    void  IncRef()                      { nRef++;           }
    USHORT DecRef()                     { return --nRef;    }
    void  SetPhysPageSize( short );
    INT32 GetPhysPages()                { return nPages;    }
    short GetPhysPageSize()             { return nPageSize; }
    SvStream* GetStrm()                 { return pStrm;     }
    void  SetStrm( SvStream*, BOOL );
    void  SetStrm( UCBStorageStream* );
    BOOL  IsWritable()                  { return pStrm->IsWritable(); }
    BOOL  Good()                        { return BOOL( nError == SVSTREAM_OK ); }
    BOOL  Bad()                         { return BOOL( nError != SVSTREAM_OK ); }
    ULONG GetError()                    { return nError;    }
    void  MoveError( StorageBase& );
    void  SetError( ULONG );
    void  ResetError();
    BOOL  Open( const String& rName, StreamMode );
    void  Close();
    BOOL  Read( INT32 nPage, void* pBuf, INT32 nPages );
    BOOL  Write( INT32 nPage, void* pBuf, INT32 nPages );
    BOOL  SetSize( INT32 nPages );
    StgPage* Find( INT32 );                 // find a cached page
    StgPage* Get( INT32, BOOL );            // get a cached page
    StgPage* Copy( INT32, INT32=STG_FREE ); // copy a page
    BOOL Commit( StgDirEntry* = NULL );     // flush all pages
    void Revert( StgDirEntry* = NULL );     // revert dirty pages
    void Clear();                           // clear the cache
};

class StgPage {
    friend class StgCache;
    StgCache* pCache;                       // the cache
    StgPage *pNext1, *pLast1;               // LRU chain
    StgPage *pNext2, *pLast2;               // ordered chain
    StgDirEntry* pOwner;                    // owner
    INT32   nPage;                          // page #
    BYTE*   pData;                          // nPageSize characters
    short   nData;                          // size of this page
    BOOL    bDirty;                         // dirty flag
    StgPage( StgCache*, short );
    ~StgPage();
public:
    void  SetDirty()                    { bDirty = TRUE;            }
    INT32 GetPage()                     { return nPage;             }
    void* GetData()                     { return pData;             }
    short GetSize()                     { return nData;             }
    void  SetOwner( StgDirEntry* p )    { pOwner = p;               }
    // routines for accessing FAT pages
    // Assume that the data is a FAT page and get/put FAT data.
    INT32 GetPage( short nOff )
    {
        if( ( nOff >= (short) ( nData / sizeof( INT32 ) ) ) || nOff < 0 )
            return -1;
        INT32 n = ((INT32*) pData )[ nOff ];
#ifdef OSL_BIGENDIAN
        return SWAPLONG(n);
#else
        return n;
#endif
    }
    void  SetPage( short, INT32 );      // put an element
};

#endif
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#pragma once
#ifndef NET_ETHERNET_HPP
#define NET_ETHERNET_HPP

#include <string>

#include <net/inet_common.hpp>

namespace net {

  /** Ethernet packet handling. */
  class Ethernet {
  public:
    static constexpr size_t ETHER_ADDR_LEN  = 6;
    static constexpr size_t MINIMUM_PAYLOAD = 46;

    /**
     *  Some big-endian ethernet types
     *
     *  From http://en.wikipedia.org/wiki/EtherType
     */
    enum ethertype_le {
      _ETH_IP4   = 0x0800,
      _ETH_ARP   = 0x0806,
      _ETH_WOL   = 0x0842,
      _ETH_IP6   = 0x86DD,
      _ETH_FLOW  = 0x8808,
      _ETH_JUMBO = 0x8870
    };

    /** Little-endian ethertypes. */
    enum ethertype {
      ETH_IP4   = 0x8,
      ETH_ARP   = 0x608,
      ETH_WOL   = 0x4208,
      ETH_IP6   = 0xdd86,
      ETH_FLOW  = 0x888,
      ETH_JUMBO = 0x7088,
      ETH_VLAN  = 0x81
    };

    // MAC address
    union addr {
      uint8_t part[ETHER_ADDR_LEN];

      struct {
        uint16_t minor;
        uint32_t major;
      } __attribute__((packed));

      addr& operator=(const addr cpy) noexcept {
        minor = cpy.minor;
        major = cpy.major;
        return *this;
      }

      // hex string representation
      std::string str() const {
        char eth_addr[17];
        sprintf(eth_addr, "%1x:%1x:%1x:%1x:%1x:%1x",
                part[0], part[1], part[2],
                part[3], part[4], part[5]);
        return eth_addr;
      }

      /** Check for equality */
      bool operator==(const addr mac) const noexcept
      {
        return strncmp(
                       reinterpret_cast<const char*>(part),
                       reinterpret_cast<const char*>(mac.part),
                       ETHER_ADDR_LEN) == 0;
      }

      static const addr MULTICAST_FRAME;
      static const addr BROADCAST_FRAME;

      static const addr IPv6mcast_01;
      static const addr IPv6mcast_02;

    }  __attribute__((packed)); //< union addr

    /** Constructor */
    explicit Ethernet(addr mac) noexcept;

    struct header {
      addr dest;
      addr src;
      unsigned short type;

    } __attribute__((packed)) ;

    /** Bottom upstream input, "Bottom up". Handle raw ethernet buffer. */
    void bottom(Packet_ptr);

    /** Delegate upstream ARP handler. */
    void set_arp_handler(upstream del)
    { arp_handler_ = del; }

    upstream get_arp_handler()
    { return arp_handler_; }

    /** Delegate upstream IPv4 handler. */
    void set_ip4_handler(upstream del)
    { ip4_handler_ = del; }

    /** Delegate upstream IPv4 handler. */
    upstream get_ip4_handler()
    { return ip4_handler_; }

    /** Delegate upstream IPv6 handler. */
    void set_ip6_handler(upstream del)
    { ip6_handler_ = del; };

    /** Delegate downstream */
    void set_physical_out(downstream del)
    { physical_out_ = del; }

    /** @return Mac address of the underlying device */
    const addr mac() const noexcept
    { return mac_; }

    /** Transmit data, with preallocated space for eth.header */
    void transmit(Packet_ptr);

  private:
    /** MAC address */
    addr mac_;

    /** Upstream OUTPUT connections */
    upstream ip4_handler_ = [](Packet_ptr){};
    upstream ip6_handler_ = [](Packet_ptr){};
    upstream arp_handler_ = [](Packet_ptr){};

    /** Downstream OUTPUT connection */
    downstream physical_out_ = [](Packet_ptr){};

    /*

      +--|IP4|---|ARP|---|IP6|---+
      |                          |
      |        Ethernet          |
      |                          |
      +---------|Phys|-----------+

    */
  }; //< class Ethernet
} // namespace net

#endif //< NET_ETHERNET_HPP
<commit_msg>Added ethernet trailer type (for CRC, but mostly to get the right bufsize)<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// 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.

#pragma once
#ifndef NET_ETHERNET_HPP
#define NET_ETHERNET_HPP

#include <string>

#include <net/inet_common.hpp>

namespace net {

  /** Ethernet packet handling. */
  class Ethernet {
  public:
    static constexpr size_t ETHER_ADDR_LEN  = 6;
    static constexpr size_t MINIMUM_PAYLOAD = 46;

    /**
     *  Some big-endian ethernet types
     *
     *  From http://en.wikipedia.org/wiki/EtherType
     */
    enum ethertype_le {
      _ETH_IP4   = 0x0800,
      _ETH_ARP   = 0x0806,
      _ETH_WOL   = 0x0842,
      _ETH_IP6   = 0x86DD,
      _ETH_FLOW  = 0x8808,
      _ETH_JUMBO = 0x8870
    };

    /** Little-endian ethertypes. */
    enum ethertype {
      ETH_IP4   = 0x8,
      ETH_ARP   = 0x608,
      ETH_WOL   = 0x4208,
      ETH_IP6   = 0xdd86,
      ETH_FLOW  = 0x888,
      ETH_JUMBO = 0x7088,
      ETH_VLAN  = 0x81
    };

    // MAC address
    union addr {
      uint8_t part[ETHER_ADDR_LEN];

      struct {
        uint16_t minor;
        uint32_t major;
      } __attribute__((packed));

      addr& operator=(const addr cpy) noexcept {
        minor = cpy.minor;
        major = cpy.major;
        return *this;
      }

      // hex string representation
      std::string str() const {
        char eth_addr[17];
        sprintf(eth_addr, "%1x:%1x:%1x:%1x:%1x:%1x",
                part[0], part[1], part[2],
                part[3], part[4], part[5]);
        return eth_addr;
      }

      /** Check for equality */
      bool operator==(const addr mac) const noexcept
      {
        return strncmp(
                       reinterpret_cast<const char*>(part),
                       reinterpret_cast<const char*>(mac.part),
                       ETHER_ADDR_LEN) == 0;
      }

      static const addr MULTICAST_FRAME;
      static const addr BROADCAST_FRAME;

      static const addr IPv6mcast_01;
      static const addr IPv6mcast_02;

    }  __attribute__((packed)); //< union addr

    /** Constructor */
    explicit Ethernet(addr mac) noexcept;

    struct header {
      addr dest;
      addr src;
      unsigned short type;

    } __attribute__((packed)) ;

    using trailer = uint32_t;

    /** Bottom upstream input, "Bottom up". Handle raw ethernet buffer. */
    void bottom(Packet_ptr);

    /** Delegate upstream ARP handler. */
    void set_arp_handler(upstream del)
    { arp_handler_ = del; }

    upstream get_arp_handler()
    { return arp_handler_; }

    /** Delegate upstream IPv4 handler. */
    void set_ip4_handler(upstream del)
    { ip4_handler_ = del; }

    /** Delegate upstream IPv4 handler. */
    upstream get_ip4_handler()
    { return ip4_handler_; }

    /** Delegate upstream IPv6 handler. */
    void set_ip6_handler(upstream del)
    { ip6_handler_ = del; };

    /** Delegate downstream */
    void set_physical_out(downstream del)
    { physical_out_ = del; }

    /** @return Mac address of the underlying device */
    const addr mac() const noexcept
    { return mac_; }

    /** Transmit data, with preallocated space for eth.header */
    void transmit(Packet_ptr);

  private:
    /** MAC address */
    addr mac_;

    /** Upstream OUTPUT connections */
    upstream ip4_handler_ = [](Packet_ptr){};
    upstream ip6_handler_ = [](Packet_ptr){};
    upstream arp_handler_ = [](Packet_ptr){};

    /** Downstream OUTPUT connection */
    downstream physical_out_ = [](Packet_ptr){};

    /*

      +--|IP4|---|ARP|---|IP6|---+
      |                          |
      |        Ethernet          |
      |                          |
      +---------|Phys|-----------+

    */
  }; //< class Ethernet
} // namespace net

#endif //< NET_ETHERNET_HPP
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <class T>
struct Node
{
	T data;
	Node<T>* left;
	Node<T>* right;
};

template <class T>
class BinaryTree
{
private:
	Node<T> *root;
	uint16_t CountElements = 0;
public:
	BinaryTree();
	~BinaryTree();
	void deleteNode(Node<T>* temp);
	void insert_node(const T&);
	void print()const;
	Node<T>*root_()const;
	Node<T> *find_node(const T&, Node<T>*)const;
	void show(Node<T>*, unsigned int)const;
	void reading(const std::string&);
	void writing(const std::string&)const;
	bool search_result(const T& value)const;
	Node<T>* get_pointer(const T& value, Node<T>* temp)const;

};

template<typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<class T>
Node<T>*BinaryTree<T>::root_()const
{
	return root;
}

template<typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
Node<T> *BinaryTree<T>::get_pointer(const T& value, Node<T>* temp)const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return get_pointer(value, temp->right);
	else return get_pointer(value, temp->left);
}

template<typename T>
bool BinaryTree<T>::search_result(const T& value)const
{
	return get_pointer(value, root);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::reading(const std::string& filename)
{
	ifstream fin(filename);
	if (root != nullptr)
		deleteNode(root);

	int k;
	fin >> k;
	T temp;
	for (int i = 0; i < k; ++i)
	{
		fin >> temp;
		insert_node(temp);
	}
	fin.close();
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::show(Node<T>* temp, unsigned int level)const
{

	if (temp)
	{
		show(temp->left, level + 1);
		for (unsigned int i = 0; i < level; i++)
			std::cout << "-";
		std::cout << temp->data << std::endl;
		show(temp->right, level + 1);
	}
}

template<typename T>
void BinaryTree<T>::out()const
{
	show(root, 0);
}
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <class T>
struct Node
{
	T data;
	Node<T>* left;
	Node<T>* right;
};

template <class T>
class BinaryTree
{
private:
	Node<T> *root;
	uint16_t CountElements = 0;
public:
	BinaryTree();
	~BinaryTree();
	void deleteNode(Node<T>* temp);
	void insert_node(const T&);
	void print()const;
	Node<T>*root_()const;
	Node<T> *find_node(const T&, Node<T>*)const;
	void show(Node<T>*, unsigned int)const;
	void out()const;
	void reading(const std::string&);
	void writing(const std::string&)const;
	bool search_result(const T& value)const;
	Node<T>* get_pointer(const T& value, Node<T>* temp)const;

};

template<typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<class T>
Node<T>*BinaryTree<T>::root_()const
{
	return root;
}

template<typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
Node<T> *BinaryTree<T>::get_pointer(const T& value, Node<T>* temp)const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return get_pointer(value, temp->right);
	else return get_pointer(value, temp->left);
}

template<typename T>
bool BinaryTree<T>::search_result(const T& value)const
{
	return get_pointer(value, root);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
		return;
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::reading(const std::string& filename)
{
	ifstream fin(filename);
	if (root != nullptr)
		deleteNode(root);

	int k;
	fin >> k;
	T temp;
	for (int i = 0; i < k; ++i)
	{
		fin >> temp;
		insert_node(temp);
	}
	fin.close();
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template<typename T>
void BinaryTree<T>::show(Node<T>* temp, unsigned int level)const
{

	if (temp)
	{
		show(temp->left, level + 1);
		for (unsigned int i = 0; i < level; i++)
			std::cout << "-";
		std::cout << temp->data << std::endl;
		show(temp->right, level + 1);
	}
}

template<typename T>
void BinaryTree<T>::out()const
{
	show(root, 0);
}
<|endoftext|>


<commit_before>// $Id: NMRSpectrum_test.C,v 1.5 2001/05/06 23:11:35 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/FORMAT/HINFile.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/STRUCTURE/fragmentDB.h>
#include <BALL/STRUCTURE/residueChecker.h>
#include <BALL/NMR/NMRSpectrum.h>
#include <BALL/NMR/peak.h>
#include <BALL/KERNEL/system.h>
///////////////////////////

START_TEST(NMRSpectrum, "$Id: NMRSpectrum_test.C,v 1.5 2001/05/06 23:11:35 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;
using namespace std;

NMRSpectrum* p;

CHECK(NMRSpectrum::NMRSpectrum())
	p = new NMRSpectrum;
	TEST_NOT_EQUAL(p, 0);
RESULT

CHECK(NMRSpectrum::~NMRSpectrum())
	delete p;
RESULT

CHECK(NMRSpectrum::setSystem(System* s)/getSystem())
	NMRSpectrum spectrum;
	System system;
	TEST_EQUAL(spectrum.getSystem(), 0)
	spectrum.setSystem(&system);
	TEST_EQUAL(spectrum.getSystem(), &system)
RESULT

CHECK(NMRSpectrum::setDensity(Size density)/getDensity())
	NMRSpectrum spectrum;
	TEST_EQUAL(spectrum.getDensity(), 100)
	spectrum.setDensity(50);
	TEST_EQUAL(spectrum.getDensity(), 50)
	spectrum.setDensity(100);
RESULT

ShiftModel sm("data/ShiftModel_test.ini");
CHECK(NMRSpectrum::setShiftModel(const ShiftModel& model))
	NMRSpectrum spectrum;
	spectrum.setShiftModel(sm);
RESULT

CHECK(NMRSpectrum::getShiftModel() const)
	NMRSpectrum spectrum;
	spectrum.setShiftModel(sm);
	// TEST_EQUAL(spectrum.getShiftModel(), sm)
RESULT

HINFile f("data/NMRSpectrum_test.hin");
System system;
f >> system;

CHECK(NMRSpectrum::calculateShifts())
	NMRSpectrum spectrum;
	spectrum.setShiftModel(sm);
	spectrum.setSystem(&system);
  spectrum.calculateShifts();
RESULT

CHECK(NMRSpectrum::createSpectrum())
	NMRSpectrum spectrum;
	spectrum.setSystem(&system);
	spectrum.setShiftModel(sm);
	spectrum.calculateShifts();
  spectrum.createSpectrum();
	TEST_EQUAL(spectrum.getPeakList().size(), 873)
RESULT

list<Peak1D> peaks;

CHECK(NMRSpectrum::getPeakList() const)
	NMRSpectrum spectrum;
	peaks = spectrum.getPeakList();
	TEST_EQUAL(peaks.size(), 0)
RESULT

CHECK(NMRSpectrum::getSpectrumMin() const )
	NMRSpectrum spectrum;
	TEST_EQUAL(spectrum.getSpectrumMin(), 0)
RESULT

CHECK(NMRSpectrum::getSpectrumMax() const )
	NMRSpectrum spectrum;
	TEST_EQUAL(spectrum.getSpectrumMax(), 0) // ???
RESULT

CHECK(NMRSpectrum::setPeakList(const list<Peak1D>& spectrum))
	NMRSpectrum spectrum;
	spectrum.setPeakList(peaks);
RESULT

CHECK(NMRSpectrum::sortSpectrum())
	NMRSpectrum spectrum;
	spectrum.sortSpectrum();
RESULT

NMRSpectrum spectrum;
spectrum.setSystem(&system);
spectrum.setShiftModel(sm);
spectrum.calculateShifts();
spectrum.sortSpectrum();
spectrum.createSpectrum();

String filename;
CHECK(NMRSpectrum::plotSpectrum(const String& filename) const )
	NEW_TMP_FILE(filename)
	spectrum.setDensity(32768);
	spectrum.plotSpectrum(filename);
	TEST_FILE(filename.c_str(), "data/NMRSpectrum_test.dat", false)
RESULT

CHECK(NMRSpectrum::plotPeaks(const String& filename) const )
	NEW_TMP_FILE(filename)
	spectrum.plotPeaks(filename);
	TEST_FILE(filename.c_str(), "data/NMRSpectrum_test/plotPeaks.txt", false)
RESULT

CHECK(NMRSpectrum::writePeaks(const String& filename) const )
	NEW_TMP_FILE(filename)
	spectrum.writePeaks(filename);
	TEST_FILE(filename.c_str(), "data/NMRSpectrum_test/writePeaks.txt", false)
RESULT

CHECK(NMRSpectrum::makeDifference(const float&, const String&, const String&, const String&))
  //BAUSTELLE
RESULT

CHECK(NMRSpectrum::setDifference(NMRSpectrum*, NMRSpectrum*, String, String))
  //BAUSTELLE
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>fixed: wrong ini file was used<commit_after>// $Id: NMRSpectrum_test.C,v 1.6 2001/05/07 00:36:52 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/FORMAT/HINFile.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/STRUCTURE/fragmentDB.h>
#include <BALL/STRUCTURE/residueChecker.h>
#include <BALL/NMR/NMRSpectrum.h>
#include <BALL/NMR/peak.h>
#include <BALL/KERNEL/system.h>
///////////////////////////

START_TEST(NMRSpectrum, "$Id: NMRSpectrum_test.C,v 1.6 2001/05/07 00:36:52 oliver Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;
using namespace std;

NMRSpectrum* p;

CHECK(NMRSpectrum::NMRSpectrum())
	p = new NMRSpectrum;
	TEST_NOT_EQUAL(p, 0);
RESULT

CHECK(NMRSpectrum::~NMRSpectrum())
	delete p;
RESULT

CHECK(NMRSpectrum::setSystem(System* s)/getSystem())
	NMRSpectrum spectrum;
	System system;
	TEST_EQUAL(spectrum.getSystem(), 0)
	spectrum.setSystem(&system);
	TEST_EQUAL(spectrum.getSystem(), &system)
RESULT

CHECK(NMRSpectrum::setDensity(Size density)/getDensity())
	NMRSpectrum spectrum;
	TEST_EQUAL(spectrum.getDensity(), 100)
	spectrum.setDensity(50);
	TEST_EQUAL(spectrum.getDensity(), 50)
	spectrum.setDensity(100);
RESULT

ShiftModel sm("data/NMRSpectrum_test.ini");
CHECK(NMRSpectrum::setShiftModel(const ShiftModel& model))
	NMRSpectrum spectrum;
	spectrum.setShiftModel(sm);
RESULT

CHECK(NMRSpectrum::getShiftModel() const)
	NMRSpectrum spectrum;
	spectrum.setShiftModel(sm);
	// TEST_EQUAL(spectrum.getShiftModel(), sm)
RESULT

HINFile f("data/NMRSpectrum_test.hin");
System system;
f >> system;

CHECK(NMRSpectrum::calculateShifts())
	NMRSpectrum spectrum;
	spectrum.setShiftModel(sm);
	spectrum.setSystem(&system);
  spectrum.calculateShifts();
RESULT

CHECK(NMRSpectrum::createSpectrum())
	NMRSpectrum spectrum;
	spectrum.setSystem(&system);
	spectrum.setShiftModel(sm);
	spectrum.calculateShifts();
  spectrum.createSpectrum();
	TEST_EQUAL(spectrum.getPeakList().size(), 873)
RESULT

list<Peak1D> peaks;

CHECK(NMRSpectrum::getPeakList() const)
	NMRSpectrum spectrum;
	peaks = spectrum.getPeakList();
	TEST_EQUAL(peaks.size(), 0)
RESULT

CHECK(NMRSpectrum::getSpectrumMin() const )
	NMRSpectrum spectrum;
	TEST_EQUAL(spectrum.getSpectrumMin(), 0)
RESULT

CHECK(NMRSpectrum::getSpectrumMax() const )
	NMRSpectrum spectrum;
	TEST_EQUAL(spectrum.getSpectrumMax(), 0) // ???
RESULT

CHECK(NMRSpectrum::setPeakList(const list<Peak1D>& spectrum))
	NMRSpectrum spectrum;
	spectrum.setPeakList(peaks);
RESULT

CHECK(NMRSpectrum::sortSpectrum())
	NMRSpectrum spectrum;
	spectrum.sortSpectrum();
RESULT

NMRSpectrum spectrum;
spectrum.setSystem(&system);
spectrum.setShiftModel(sm);
spectrum.calculateShifts();
spectrum.sortSpectrum();
spectrum.createSpectrum();

String filename;
CHECK(NMRSpectrum::plotSpectrum(const String& filename) const )
	NEW_TMP_FILE(filename)
	spectrum.setDensity(32768);
	spectrum.plotSpectrum(filename);
	TEST_FILE(filename.c_str(), "data/NMRSpectrum_test.dat", false)
RESULT

CHECK(NMRSpectrum::plotPeaks(const String& filename) const )
	NEW_TMP_FILE(filename)
	spectrum.plotPeaks(filename);
	TEST_FILE(filename.c_str(), "data/NMRSpectrum_test/plotPeaks.txt", false)
RESULT

CHECK(NMRSpectrum::writePeaks(const String& filename) const )
	NEW_TMP_FILE(filename)
	spectrum.writePeaks(filename);
	TEST_FILE(filename.c_str(), "data/NMRSpectrum_test/writePeaks.txt", false)
RESULT

CHECK(NMRSpectrum::makeDifference(const float&, const String&, const String&, const String&))
  //BAUSTELLE
RESULT

CHECK(NMRSpectrum::setDifference(NMRSpectrum*, NMRSpectrum*, String, String))
  //BAUSTELLE
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before>#include "ImageLoader.h"
#include "RenderContext.h"
#include "GUM_AsyncTask.h"
#include <gum/Config.h>
#include "Image.h"

#include <gimg_import.h>
#include <gimg_typedef.h>
#include <gimg_pvr.h>
#include <gimg_etc2.h>
#include <bimp/FileLoader.h>
#include <bimp/BIMP_ImportStream.h>
#include <timp/TextureFormat.h>
#include <timp/TextureLoader.h>
#include <unirender/UR_RenderContext.h>

#include <stdlib.h>

namespace gum
{

ImageLoader::ImageLoader(const std::string& filepath)
	: m_filepath(filepath)
	, m_id(0)
	, m_format(0)
	, m_width(0)
	, m_height(0)
{
}

bool ImageLoader::Load()
{
	if (m_filepath.find(".ept") != std::string::npos) {
		return LoadBin();
	} else {
		return LoadRaw();
	}
}

class FileLoader : public bimp::FileLoader
{
public:
	FileLoader(const std::string& filepath, bool use_cache, void (*parser_cb)(const void* data, size_t size, void* ud), void* ud)
		: bimp::FileLoader(filepath, use_cache)
		, m_parser_cb(parser_cb)
		, m_ud(ud)
	{}

protected:
	virtual void OnLoad(bimp::ImportStream& is)
	{
		m_parser_cb(is.Stream(), is.Size(), m_ud);
	}

private:
	void (*m_parser_cb)(const void* data, size_t size, void* ud);
	void* m_ud;

}; // FileLoader

static
void _load_cb(const char* filepath, void (*unpack)(const void* data, size_t size, void* ud), void* ud)
{
	FileLoader loader(filepath, false, unpack, ud);
	loader.Load();
}

static
void _parser_cb(const void* data, size_t size, void* ud)
{
	timp::TextureLoader loader(static_cast<const char*>(data), size);
	loader.Load();

	Image* img = static_cast<Image*>(ud);
	const void* pixels = loader.GetData();
	int width = loader.GetWidth(),
		height = loader.GetHeight();
	RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
	img->SetLoadFinished(true);
}

static
void _release_cb(void* ud)
{
	Image* img = static_cast<Image*>(ud);
	img->RemoveReference();
}

bool ImageLoader::AsyncLoad(int format, int width, int height, Image* img)
{
	if (m_filepath.find(".ept") == std::string::npos) {
		return false;
	}

	m_id = RenderContext::Instance()->GetImpl()->CreateTextureID(width, height, format);
	m_format = format;
	m_width = width;
	m_height = height;

	img->SetLoadFinished(false);
	img->AddReference();
	AsyncTask::Instance()->Load(m_filepath, _load_cb, _parser_cb, _release_cb, img);

	return true;
}

bool ImageLoader::LoadRaw()
{
	int w, h, fmt;
	uint8_t* pixels = gimg_import(m_filepath.c_str(), &w, &h, &fmt);
	if (!pixels) {
		return false;
	}

	if (fmt == GPF_RGBA && Config::Instance()->GetPreMulAlpha()) {
		gimg_pre_mul_alpha(pixels, w, h);
	}

	m_width = w;
	m_height = h;

	timp::TEXTURE_FORMAT tf = timp::TEXTURE_INVALID;
	switch (fmt)
	{
	case GPF_ALPHA: case GPF_LUMINANCE: case GPF_LUMINANCE_ALPHA:
		tf = timp::TEXTURE_A8;
		break;
	case GPF_RGB:
		tf = timp::TEXTURE_RGB;
		break;
	case GPF_RGBA:
		tf = timp::TEXTURE_RGBA8;
		break;
	}

	m_format = tf;
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(pixels, w, h, tf);
	free(pixels);

	return true;
}

bool ImageLoader::LoadBin()
{
	bool ret = true;

	timp::TextureLoader loader(m_filepath);
	loader.Load();

	m_format = loader.GetFormat();
	m_width  = loader.GetWidth();
	m_height = loader.GetHeight();
	switch (m_format)
	{
	case timp::TEXTURE_RGBA4: case timp::TEXTURE_RGBA8:
		m_id = RenderContext::Instance()->GetImpl()->CreateTexture(static_cast<const uint8_t*>(loader.GetData()), m_width, m_height, m_format);
		break;
	case timp::TEXTURE_PVR2:
		ret = DecodePVR2(loader.GetData());
		break;
	case timp::TEXTURE_PVR4:
		ret = DecodePVR4(loader.GetData());
		break;
	case timp::TEXTURE_ETC1:
		ret = false;
		break;
	case timp::TEXTURE_ETC2:
		ret = DecodeETC2(loader.GetData());
		break;
	}

	return ret;
}

bool ImageLoader::DecodePVR2(const void* data)
{
#if defined( __APPLE__ ) && !defined(__MACOSX)
//	int internal_format = 0;
//	internal_format = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, ur::TEXTURE_PVR2);
	return true;
#else
	return false;
#endif
}

bool ImageLoader::DecodePVR4(const void* data)
{
#if defined( __APPLE__ ) && !defined(__MACOSX)
//	int internal_format = 0;
//	internal_format = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, ur::TEXTURE_PVR4);
#else
	uint8_t* uncompressed = gimg_pvr_decode(static_cast<const uint8_t*>(data), m_width, m_height);
	gimg_revert_y(uncompressed, m_width, m_height, GPF_RGBA);
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(uncompressed, m_width, m_height, timp::TEXTURE_RGBA8);
	free(uncompressed);
#endif
	return true;
}

bool ImageLoader::DecodeETC2(const void* data)
{
#ifdef __ANDROID__
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, timp::TEXTURE_ETC2);
#elif defined( __APPLE__ ) && !defined(__MACOSX)
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, timp::TEXTURE_ETC2);
#else
	uint8_t* uncompressed = gimg_etc2_decode(static_cast<const uint8_t*>(data), m_width, m_height, ETC2PACKAGE_RGBA_NO_MIPMAPS);
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(uncompressed, m_width, m_height, timp::TEXTURE_RGBA8);
	free(uncompressed);
#endif // __ANDROID__
	return true;
}

}
<commit_msg>[FIXED] load compressed tex async<commit_after>#include "ImageLoader.h"
#include "RenderContext.h"
#include "GUM_AsyncTask.h"
#include <gum/Config.h>
#include "Image.h"

#include <gimg_import.h>
#include <gimg_typedef.h>
#include <gimg_pvr.h>
#include <gimg_etc2.h>
#include <bimp/FileLoader.h>
#include <bimp/BIMP_ImportStream.h>
#include <timp/TextureFormat.h>
#include <timp/TextureLoader.h>
#include <unirender/UR_RenderContext.h>

#include <stdlib.h>

namespace gum
{

ImageLoader::ImageLoader(const std::string& filepath)
	: m_filepath(filepath)
	, m_id(0)
	, m_format(0)
	, m_width(0)
	, m_height(0)
{
}

bool ImageLoader::Load()
{
	if (m_filepath.find(".ept") != std::string::npos) {
		return LoadBin();
	} else {
		return LoadRaw();
	}
}

class FileLoader : public bimp::FileLoader
{
public:
	FileLoader(const std::string& filepath, bool use_cache, void (*parser_cb)(const void* data, size_t size, void* ud), void* ud)
		: bimp::FileLoader(filepath, use_cache)
		, m_parser_cb(parser_cb)
		, m_ud(ud)
	{}

protected:
	virtual void OnLoad(bimp::ImportStream& is)
	{
		m_parser_cb(is.Stream(), is.Size(), m_ud);
	}

private:
	void (*m_parser_cb)(const void* data, size_t size, void* ud);
	void* m_ud;

}; // FileLoader

static
void _load_cb(const char* filepath, void (*unpack)(const void* data, size_t size, void* ud), void* ud)
{
	FileLoader loader(filepath, false, unpack, ud);
	loader.Load();
}

static
void _parser_cb(const void* data, size_t size, void* ud)
{
	timp::TextureLoader loader(static_cast<const char*>(data), size);
	loader.Load();

	Image* img = static_cast<Image*>(ud);
	const void* pixels = loader.GetData();
	int width = loader.GetWidth(),
		height = loader.GetHeight();
	int format = loader.GetFormat();
	switch (format)
	{
	case timp::TEXTURE_RGBA4: case timp::TEXTURE_RGBA8:
		RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
		break;
	case timp::TEXTURE_PVR2:
#if defined( __APPLE__ ) && !defined(__MACOSX)
		RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
#endif
		break;
	case timp::TEXTURE_PVR4:
		{
#if defined( __APPLE__ ) && !defined(__MACOSX)
			RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
#else
			uint8_t* uncompressed = gimg_pvr_decode(static_cast<const uint8_t*>(pixels), width, height);
			gimg_revert_y(uncompressed, width, height, GPF_RGBA);
			RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), uncompressed, width, height);
			free(uncompressed);
#endif
		}
		break;
	case timp::TEXTURE_ETC1:
		break;
	case timp::TEXTURE_ETC2:
		{
#ifdef __ANDROID__
			RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
#elif defined( __APPLE__ ) && !defined(__MACOSX)
			RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
#elif defined _WIN32
			RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), pixels, width, height);
#else
			uint8_t* uncompressed = gimg_etc2_decode(static_cast<const uint8_t*>(pixels), width, height, ETC2PACKAGE_RGBA_NO_MIPMAPS);
			RenderContext::Instance()->GetImpl()->UpdateTexture(img->GetTexID(), uncompressed, width, height);
			free(uncompressed);
#endif // __ANDROID__
		}
		break;
	}
	img->SetLoadFinished(true);
}

static
void _release_cb(void* ud)
{
	Image* img = static_cast<Image*>(ud);
	img->RemoveReference();
}

bool ImageLoader::AsyncLoad(int format, int width, int height, Image* img)
{
	if (m_filepath.find(".ept") == std::string::npos) {
		return false;
	}

	m_id = RenderContext::Instance()->GetImpl()->CreateTextureID(width, height, format);
	m_format = format;
	m_width = width;
	m_height = height;

	img->SetLoadFinished(false);
	img->AddReference();
	AsyncTask::Instance()->Load(m_filepath, _load_cb, _parser_cb, _release_cb, img);

	return true;
}

bool ImageLoader::LoadRaw()
{
	int w, h, fmt;
	uint8_t* pixels = gimg_import(m_filepath.c_str(), &w, &h, &fmt);
	if (!pixels) {
		return false;
	}

	if (fmt == GPF_RGBA && Config::Instance()->GetPreMulAlpha()) {
		gimg_pre_mul_alpha(pixels, w, h);
	}

	m_width = w;
	m_height = h;

	timp::TEXTURE_FORMAT tf = timp::TEXTURE_INVALID;
	switch (fmt)
	{
	case GPF_ALPHA: case GPF_LUMINANCE: case GPF_LUMINANCE_ALPHA:
		tf = timp::TEXTURE_A8;
		break;
	case GPF_RGB:
		tf = timp::TEXTURE_RGB;
		break;
	case GPF_RGBA:
		tf = timp::TEXTURE_RGBA8;
		break;
	}

	m_format = tf;
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(pixels, w, h, tf);
	free(pixels);

	return true;
}

bool ImageLoader::LoadBin()
{
	bool ret = true;

	timp::TextureLoader loader(m_filepath);
	loader.Load();

	m_format = loader.GetFormat();
	m_width  = loader.GetWidth();
	m_height = loader.GetHeight();
	switch (m_format)
	{
	case timp::TEXTURE_RGBA4: case timp::TEXTURE_RGBA8:
		m_id = RenderContext::Instance()->GetImpl()->CreateTexture(static_cast<const uint8_t*>(loader.GetData()), m_width, m_height, m_format);
		break;
	case timp::TEXTURE_PVR2:
		ret = DecodePVR2(loader.GetData());
		break;
	case timp::TEXTURE_PVR4:
		ret = DecodePVR4(loader.GetData());
		break;
	case timp::TEXTURE_ETC1:
		ret = false;
		break;
	case timp::TEXTURE_ETC2:
		ret = DecodeETC2(loader.GetData());
		break;
	}

	return ret;
}

bool ImageLoader::DecodePVR2(const void* data)
{
#if defined( __APPLE__ ) && !defined(__MACOSX)
//	int internal_format = 0;
//	internal_format = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, ur::TEXTURE_PVR2);
	return true;
#else
	return false;
#endif
}

bool ImageLoader::DecodePVR4(const void* data)
{
#if defined( __APPLE__ ) && !defined(__MACOSX)
//	int internal_format = 0;
//	internal_format = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, ur::TEXTURE_PVR4);
#else
	uint8_t* uncompressed = gimg_pvr_decode(static_cast<const uint8_t*>(data), m_width, m_height);
	gimg_revert_y(uncompressed, m_width, m_height, GPF_RGBA);
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(uncompressed, m_width, m_height, timp::TEXTURE_RGBA8);
	free(uncompressed);
#endif
	return true;
}

bool ImageLoader::DecodeETC2(const void* data)
{
#ifdef __ANDROID__
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, timp::TEXTURE_ETC2);
#elif defined( __APPLE__ ) && !defined(__MACOSX)
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, timp::TEXTURE_ETC2);
#elif defined _WIN32
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(data, m_width, m_height, timp::TEXTURE_ETC2);
#else
	uint8_t* uncompressed = gimg_etc2_decode(static_cast<const uint8_t*>(data), m_width, m_height, ETC2PACKAGE_RGBA_NO_MIPMAPS);
	m_id = RenderContext::Instance()->GetImpl()->CreateTexture(uncompressed, m_width, m_height, timp::TEXTURE_RGBA8);
	free(uncompressed);
#endif // __ANDROID__
	return true;
}

}
<|endoftext|>


<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Authors: Ethan Coon (ecoon@lanl.gov)
*/

#include "MatrixMFD.hh"
#include "MatrixMFD_Factory.hh"
#include "Function.hh"
#include "FunctionFactory.hh"

#include "snow_distribution_evaluator.hh"

namespace Amanzi {
namespace Flow {
namespace FlowRelations {

SnowDistributionEvaluator::SnowDistributionEvaluator(Teuchos::ParameterList& plist) :
    SecondaryVariableFieldEvaluator(plist),
    assembled_(false) {
  my_key_ = plist_.get<std::string>("precipitation snow field", "precipitation_snow");

  elev_key_ = plist_.get<std::string>("elevation key", "elevation");
  dependencies_.insert(elev_key_);
  slope_key_ = plist_.get<std::string>("slope key", "slope_magnitude");
  dependencies_.insert(slope_key_);
  pd_key_ = plist_.get<std::string>("ponded depth key", "ponded_depth");
  dependencies_.insert(pd_key_);
  snow_height_key_ = plist_.get<std::string>("snow height key", "snow_depth");
  dependencies_.insert(snow_height_key_);

  mesh_name_ = plist_.get<std::string>("mesh name", "surface");
  manning_ = plist_.get<double>("manning coefficient", 1.);

  if (mesh_name_ == "domain") {
    cell_vol_key_ = "cell_volume";
  } else {
    cell_vol_key_ = mesh_name_+std::string("_cell_volume");
  }
  dependencies_.insert(cell_vol_key_);

  FunctionFactory fac;
  precip_func_ = Teuchos::rcp(fac.Create(plist_.sublist("precipitation function")));
}

SnowDistributionEvaluator::SnowDistributionEvaluator(const SnowDistributionEvaluator& other) :
    SecondaryVariableFieldEvaluator(other),
    elev_key_(other.elev_key_),
    slope_key_(other.slope_key_),
    pd_key_(other.pd_key_),
    snow_height_key_(other.snow_height_key_),
    cell_vol_key_(other.cell_vol_key_),
    precip_func_(other.precip_func_),
    manning_(other.manning_),
    assembled_(other.assembled_),
    mesh_name_(other.mesh_name_),
    matrix_(other.matrix_) {}

void SnowDistributionEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result) {
  if (!assembled_) AssembleOperator_(S);

  result->PutScalar(0.);

  double dt = *S->GetScalarData("dt");
  double time = S->time();
  double Qe = (*precip_func_)(&time);
  if (Qe * dt > 0.) {
    Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
    int nfaces = mesh->num_entities(AmanziMesh::FACE, AmanziMesh::OWNED);
    int ncells = mesh->num_entities(AmanziMesh::CELL, AmanziMesh::OWNED);
    std::vector<Operators::MatrixBC> bc_markers(nfaces, Operators::MATRIX_BC_NULL);
    std::vector<double> bc_values(nfaces, 0.0);

    Teuchos::RCP<CompositeVector> hz = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> residual = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> du = Teuchos::rcp(new CompositeVector(*result));

    Teuchos::RCP<CompositeVector> Krel_c = Teuchos::rcp(new CompositeVector(*result));
    CompositeVectorSpace Krel_f_space;
    Krel_f_space.SetMesh(mesh)->SetComponent("face",AmanziMesh::FACE,1);
    Teuchos::RCP<CompositeVector> Krel_uw = Teuchos::rcp(new CompositeVector(Krel_f_space));

    const Epetra_MultiVector& slope = *S->GetFieldData(slope_key_)->ViewComponent("cell",false);
    const Epetra_MultiVector& cv = *S->GetFieldData(cell_vol_key_)->ViewComponent("cell",false);

    int n_cycles = 10;
    result->PutScalar(Qe*dt);
    for (int n=0; n!=n_cycles; ++n) {
      std::cout << "SNOW INNER ITERATE " << n << std::endl;

      // update snow potential, z + h_pd + h_s + Qe*dt
      *hz = *result;
      hz->Update(1., *S->GetFieldData(elev_key_),
                 1., *S->GetFieldData(pd_key_), 1.);
      hz->Update(1., *S->GetFieldData(snow_height_key_), 1.);

      // update Krel
      {
        Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",false);
        const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
        for (int c=0; c!=ncells; ++c) {
          Krel_c_vec[0][c] = std::pow(std::max(result_c[0][c],0.), 4./3)
              / (std::sqrt(std::max(slope[0][c], 1.e-4)) * manning_);
        }
      }

      // communicate and upwind
      Krel_c->ScatterMasterToGhosted();
      hz->ScatterMasterToGhosted();
      {
        Epetra_MultiVector& Krel_uw_vec = *Krel_uw->ViewComponent("face",false);
        const Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",true);
        const Epetra_MultiVector& hz_c = *hz->ViewComponent("cell",true);
        for (int f=0; f!=nfaces; ++f) {
          AmanziMesh::Entity_ID_List cells;
          mesh->face_get_cells(f,AmanziMesh::USED,&cells);
          if (cells.size() == 1) {
            Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
          } else {
            if (hz_c[0][cells[0]] > hz_c[0][cells[1]]) {
              Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
            } else {
              Krel_uw_vec[0][f] = Krel_c_vec[0][cells[1]];
            }
          }
        }
      }

      // Re-assemble
      matrix_->CreateMFDstiffnessMatrices(Krel_uw.ptr());
      matrix_->CreateMFDrhsVectors();
      matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
      matrix_->AssembleGlobalMatrices();

      // Apply the operator to get a residual
      matrix_->ComputeNegativeResidual(*hz, residual.ptr());

      // Apply the accumulation term
      // Apply the source term
      Epetra_MultiVector& residual_c = *residual->ViewComponent("cell",false);
      const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
      for (int c=0; c!=ncells; ++c) {
        residual_c[0][c] += cv[0][c] * result_c[0][c];
        residual_c[0][c] -= cv[0][c] * dt * Qe;
      }

      // smooth to find a correction
      double norm(0.);
      residual->NormInf(&norm);
      if (norm < 1.e-4) {
        break;
      }

      du->PutScalar(0.);
      // PC
      std::vector<double>& Acc_cells = matrix_->Acc_cells();
      for (int c=0; c!=ncells; ++c) {
        Acc_cells[c] += cv[0][c];
      }
      matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
      matrix_->AssembleGlobalMatrices();
      matrix_->ComputeSchurComplement(bc_markers, bc_values);
      matrix_->UpdatePreconditioner();
      matrix_->ApplyInverse(*residual, *du);

      // apply correction
      std::cout << "correction = " << std::endl;
      du->Print(std::cout);

      result->Update(-1., *du, 1.);

      // apply correction
      std::cout << "new iterate = " << std::endl;
      result->Print(std::cout);

    }

    // get Q back
    result->Scale(1./dt);
  }
}

// This is hopefully never called?
void SnowDistributionEvaluator::EvaluateFieldPartialDerivative_(const Teuchos::Ptr<State>& S,
        Key wrt_key, const Teuchos::Ptr<CompositeVector>& results) {
  ASSERT(0);
}

void
SnowDistributionEvaluator::AssembleOperator_(const Teuchos::Ptr<State>& S) {
  Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
  matrix_ = Operators::CreateMatrixMFD(plist_.sublist("smoothing operator"), mesh);

  matrix_->set_symmetric(true);
  matrix_->SymbolicAssembleGlobalMatrices();
  matrix_->CreateMFDmassMatrices(Teuchos::null);
  matrix_->InitPreconditioner();
}

} //namespace
} //namespace
} //namespace
<commit_msg>better logging in snow distribution (still needs more work<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Authors: Ethan Coon (ecoon@lanl.gov)
*/

#include "MatrixMFD.hh"
#include "MatrixMFD_Factory.hh"
#include "Function.hh"
#include "FunctionFactory.hh"

#include "snow_distribution_evaluator.hh"

namespace Amanzi {
namespace Flow {
namespace FlowRelations {

SnowDistributionEvaluator::SnowDistributionEvaluator(Teuchos::ParameterList& plist) :
    SecondaryVariableFieldEvaluator(plist),
    assembled_(false) {
  my_key_ = plist_.get<std::string>("precipitation snow field", "precipitation_snow");

  elev_key_ = plist_.get<std::string>("elevation key", "elevation");
  dependencies_.insert(elev_key_);
  slope_key_ = plist_.get<std::string>("slope key", "slope_magnitude");
  dependencies_.insert(slope_key_);
  pd_key_ = plist_.get<std::string>("ponded depth key", "ponded_depth");
  dependencies_.insert(pd_key_);
  snow_height_key_ = plist_.get<std::string>("snow height key", "snow_depth");
  dependencies_.insert(snow_height_key_);

  mesh_name_ = plist_.get<std::string>("mesh name", "surface");
  manning_ = plist_.get<double>("manning coefficient", 1.);

  if (mesh_name_ == "domain") {
    cell_vol_key_ = "cell_volume";
  } else {
    cell_vol_key_ = mesh_name_+std::string("_cell_volume");
  }
  dependencies_.insert(cell_vol_key_);

  FunctionFactory fac;
  precip_func_ = Teuchos::rcp(fac.Create(plist_.sublist("precipitation function")));
}

SnowDistributionEvaluator::SnowDistributionEvaluator(const SnowDistributionEvaluator& other) :
    SecondaryVariableFieldEvaluator(other),
    elev_key_(other.elev_key_),
    slope_key_(other.slope_key_),
    pd_key_(other.pd_key_),
    snow_height_key_(other.snow_height_key_),
    cell_vol_key_(other.cell_vol_key_),
    precip_func_(other.precip_func_),
    manning_(other.manning_),
    assembled_(other.assembled_),
    mesh_name_(other.mesh_name_),
    matrix_(other.matrix_) {}

void SnowDistributionEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result) {
  if (!assembled_) AssembleOperator_(S);

  result->PutScalar(0.);

  double dt = *S->GetScalarData("dt");
  double time = S->time();
  double Qe = (*precip_func_)(&time);
  if (Qe * dt > 0.) {
    Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
    int nfaces = mesh->num_entities(AmanziMesh::FACE, AmanziMesh::OWNED);
    int ncells = mesh->num_entities(AmanziMesh::CELL, AmanziMesh::OWNED);
    std::vector<Operators::MatrixBC> bc_markers(nfaces, Operators::MATRIX_BC_NULL);
    std::vector<double> bc_values(nfaces, 0.0);

    Teuchos::RCP<CompositeVector> hz = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> residual = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> du = Teuchos::rcp(new CompositeVector(*result));

    Teuchos::RCP<CompositeVector> Krel_c = Teuchos::rcp(new CompositeVector(*result));
    CompositeVectorSpace Krel_f_space;
    Krel_f_space.SetMesh(mesh)->SetComponent("face",AmanziMesh::FACE,1);
    Teuchos::RCP<CompositeVector> Krel_uw = Teuchos::rcp(new CompositeVector(Krel_f_space));

    const Epetra_MultiVector& slope = *S->GetFieldData(slope_key_)->ViewComponent("cell",false);
    const Epetra_MultiVector& cv = *S->GetFieldData(cell_vol_key_)->ViewComponent("cell",false);

    int n_cycles = 10;
    int i_cycle = 0;
    double norm;
    result->PutScalar(Qe*dt);
    for (int n=0; n!=n_cycles; ++n) {
      i_cycle = n;
      std::cout << "SNOW INNER ITERATE " << n << std::endl;

      // update snow potential, z + h_pd + h_s + Qe*dt
      *hz = *result;
      hz->Update(1., *S->GetFieldData(elev_key_),
                 1., *S->GetFieldData(pd_key_), 1.);
      hz->Update(1., *S->GetFieldData(snow_height_key_), 1.);

      // update Krel
      {
        Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",false);
        const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
        for (int c=0; c!=ncells; ++c) {
          Krel_c_vec[0][c] = std::pow(std::max(result_c[0][c],0.), 4./3)
              / (std::sqrt(std::max(slope[0][c], 1.e-4)) * manning_);
        }
      }

      // communicate and upwind
      Krel_c->ScatterMasterToGhosted();
      hz->ScatterMasterToGhosted();
      {
        Epetra_MultiVector& Krel_uw_vec = *Krel_uw->ViewComponent("face",false);
        const Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",true);
        const Epetra_MultiVector& hz_c = *hz->ViewComponent("cell",true);
        for (int f=0; f!=nfaces; ++f) {
          AmanziMesh::Entity_ID_List cells;
          mesh->face_get_cells(f,AmanziMesh::USED,&cells);
          if (cells.size() == 1) {
            Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
          } else {
            if (hz_c[0][cells[0]] > hz_c[0][cells[1]]) {
              Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
            } else {
              Krel_uw_vec[0][f] = Krel_c_vec[0][cells[1]];
            }
          }
        }
      }

      // Re-assemble
      matrix_->CreateMFDstiffnessMatrices(Krel_uw.ptr());
      matrix_->CreateMFDrhsVectors();
      matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
      matrix_->AssembleGlobalMatrices();

      // Apply the operator to get a residual
      matrix_->ComputeNegativeResidual(*hz, residual.ptr());

      // Apply the accumulation term
      // Apply the source term
      Epetra_MultiVector& residual_c = *residual->ViewComponent("cell",false);
      const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
      for (int c=0; c!=ncells; ++c) {
        residual_c[0][c] += cv[0][c] * result_c[0][c];
        residual_c[0][c] -= cv[0][c] * dt * Qe;
      }

      // smooth to find a correction
      residual->NormInf(&norm);
      if (norm < 1.e-4) {
        break;
      }

      du->PutScalar(0.);
      // PC
      std::vector<double>& Acc_cells = matrix_->Acc_cells();
      for (int c=0; c!=ncells; ++c) {
        Acc_cells[c] += cv[0][c];
      }
      matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
      matrix_->AssembleGlobalMatrices();
      matrix_->ComputeSchurComplement(bc_markers, bc_values);
      matrix_->UpdatePreconditioner();
      matrix_->ApplyInverse(*residual, *du);

      // apply correction
      result->Update(-1., *du, 1.);

      // log
      std::cout << "Snow Distribution: itr=" << i_cycle << ", norm=" << norm << std::endl;

    }
    std::cout << "Snow Distribution finished: itr=" << i_cycle << ", norm=" << norm << std::endl;

    // get Q back
    result->Scale(1./dt);
  }
}

// This is hopefully never called?
void SnowDistributionEvaluator::EvaluateFieldPartialDerivative_(const Teuchos::Ptr<State>& S,
        Key wrt_key, const Teuchos::Ptr<CompositeVector>& results) {
  ASSERT(0);
}

void
SnowDistributionEvaluator::AssembleOperator_(const Teuchos::Ptr<State>& S) {
  Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
  matrix_ = Operators::CreateMatrixMFD(plist_.sublist("smoothing operator"), mesh);

  matrix_->set_symmetric(true);
  matrix_->SymbolicAssembleGlobalMatrices();
  matrix_->CreateMFDmassMatrices(Teuchos::null);
  matrix_->InitPreconditioner();
}

} //namespace
} //namespace
} //namespace
<|endoftext|>