text:
#include "tensorflow/compiler/xla/pjrt/pjrt_c_api_client.h"

#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/string_view.h"
#include "mlir/Bytecode/BytecodeWriter.h"  // from @llvm-project
#include "tensorflow/compiler/xla/pjrt/c/pjrt_c_api.h"
// TODO(skyewm): remove when everything goes through C API
#include "tensorflow/compiler/xla/pjrt/c/pjrt_c_api_helpers.h"
#include "tensorflow/compiler/xla/pjrt/c/pjrt_c_api_wrapper_impl.h"
#include "tensorflow/compiler/xla/pjrt/pjrt_client.h"
#include "tensorflow/compiler/xla/pjrt/pjrt_future.h"
#include "tensorflow/compiler/xla/shape.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/stream_executor/tpu/pjrt_api.h"
#include "tensorflow/compiler/xla/stream_executor/tpu/tpu_initializer_helper.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/tsl/platform/status.h"

// TODO(b/238999986): Remove this when we have decomposed shape.
#include "tensorflow/compiler/xla/stream_executor/tpu/c_api_conversions.h"

namespace xla {
bool kPjRtCApiBypass = false;

// Helper macros

// Return error status if not success and frees the PJRT_Error returned by
// `expr`.
#define RETURN_STATUS_IF_ERROR(expr, c_api)                             \
  do {                                                                  \
    PJRT_Error* error = (expr);                                         \
    std::unique_ptr<PJRT_Error, pjrt::PJRT_ErrorDeleter> _error(        \
        error, pjrt::MakeErrorDeleter(c_api));                          \
    xla::Status _status = pjrt::PjrtErrorToStatus(_error.get(), c_api); \
    if (!_status.ok()) {                                                \
      return _status;                                                   \
    }                                                                   \
  } while (false)

// ---------------------------------- Client -----------------------------------

PjRtCApiClient::PjRtCApiClient(const PJRT_Api* c_api, PJRT_Client* c_client)
    : c_api_(c_api),
      c_client_(std::unique_ptr<PJRT_Client, ::pjrt::PJRT_ClientDeleter>(
          c_client, ::pjrt::MakeClientDeleter(c_api))) {
  wrapped_ = c_client_->client.get();

  InitDevices();
  LOG(INFO) << "PjRtCApiClient created.";
}

void PjRtCApiClient::InitDevices() {
  PJRT_Client_Devices_Args devices_args;
  devices_args.struct_size = PJRT_Client_Devices_Args_STRUCT_SIZE;
  devices_args.priv = nullptr;
  devices_args.client = c_client_.get();

  pjrt::LogFatalIfPjrtError(c_api_->PJRT_Client_Devices(&devices_args), c_api_);

  const size_t n = devices_args.num_devices;
  wrapped_device_map_.reserve(n);
  c_to_cpp_device_map_.reserve(n);
  owned_devices_.reserve(n);
  devices_.reserve(n);

  for (size_t i = 0; i < n; ++i) {
    PJRT_Device* device = devices_args.devices[i];
    std::unique_ptr<PjRtCApiDevice>& cpp_device = owned_devices_.emplace_back(
        std::make_unique<PjRtCApiDevice>(device, this));
    devices_.push_back(cpp_device.get());
    c_to_cpp_device_map_[device] = cpp_device.get();
    // Map the wrapped PjRtDevice* to the PjRtCApiDevice* that wraps it.
    // TODO(b/237017893): remove `wrapped_device_map_` and replace it with
    // `c_api_device_map_`
    wrapped_device_map_[device->device] = cpp_device.get();
  }

  PJRT_Client_AddressableDevices_Args address_args;
  address_args.struct_size = PJRT_Client_AddressableDevices_Args_STRUCT_SIZE;
  address_args.priv = nullptr;
  address_args.client = c_client_.get();

  pjrt::LogFatalIfPjrtError(
      c_api_->PJRT_Client_AddressableDevices(&address_args), c_api_);

  const size_t m = address_args.num_addressable_devices;
  addressable_devices_.reserve(m);

  for (size_t i = 0; i < m; ++i) {
    PJRT_Device* c_device = address_args.addressable_devices[i];
    addressable_devices_.push_back(GetCppDevice(c_device));
  }
}

int PjRtCApiClient::device_count() const { return devices_.size(); }

int PjRtCApiClient::addressable_device_count() const {
  return addressable_devices_.size();
}

absl::Span<PjRtDevice* const> PjRtCApiClient::devices() const {
  return devices_;
}

absl::Span<PjRtDevice* const> PjRtCApiClient::addressable_devices() const {
  return addressable_devices_;
}

absl::string_view PjRtCApiClient::platform_name() const {
  PJRT_Client_PlatformName_Args args;
  args.client = c_client_.get();
  args.struct_size = PJRT_Client_PlatformName_Args_STRUCT_SIZE;
  args.priv = nullptr;
  pjrt::LogFatalIfPjrtError(c_api_->PJRT_Client_PlatformName(&args), c_api_);

  absl::string_view platform_name(args.platform_name, args.platform_name_size);
  return platform_name;
}

int PjRtCApiClient::process_index() const {
  PJRT_Client_ProcessIndex_Args process_index_args;
  process_index_args.struct_size = PJRT_Client_ProcessIndex_Args_STRUCT_SIZE;
  process_index_args.priv = nullptr;
  process_index_args.client = c_client_.get();
  pjrt::LogFatalIfPjrtError(
      c_api_->PJRT_Client_ProcessIndex(&process_index_args), c_api_);

  return process_index_args.process_index;
}

absl::string_view PjRtCApiClient::platform_version() const {
  PJRT_Client_PlatformVersion_Args args;
  args.struct_size = PJRT_Client_PlatformVersion_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.client = c_client_.get();
  pjrt::LogFatalIfPjrtError(c_api_->PJRT_Client_PlatformVersion(&args), c_api_);

  absl::string_view platform_version(args.platform_version,
                                     args.platform_version_size);
  return platform_version;
}

static DeviceAssignment CalculateDefaultAssignment(
    int num_replicas, int num_partitions,
    absl::Span<const int> device_assignment) {
  DeviceAssignment cpp_device_assignment(num_replicas, num_partitions);
  const int* iterator = device_assignment.begin();
  for (int replica = 0; replica < num_replicas; ++replica) {
    for (int partition = 0; partition < num_partitions; ++partition) {
      cpp_device_assignment(replica, partition) = *(iterator++);
    }
  }
  return cpp_device_assignment;
}

StatusOr<DeviceAssignment> PjRtCApiClient::GetDefaultDeviceAssignment(
    int num_replicas, int num_partitions) const {
  PJRT_Client_DefaultDeviceAssignment_Args args;
  args.struct_size = PJRT_Client_DefaultDeviceAssignment_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.client = c_client_.get();
  args.num_replicas = num_replicas;
  args.num_partitions = num_partitions;
  std::vector<int> assignment_buffer(num_replicas * num_partitions);
  args.default_assignment_size = assignment_buffer.size();
  args.default_assignment = assignment_buffer.data();
  RETURN_STATUS_IF_ERROR(c_api_->PJRT_Client_DefaultDeviceAssignment(&args),
                         c_api_);
  absl::Span<const int> param{args.default_assignment,
                              args.default_assignment_size};
  return CalculateDefaultAssignment(args.num_replicas, args.num_partitions,
                                    param);
}

StatusOr<std::optional<std::string>> PjRtCApiClient::ExecutableFingerprint(
    const PjRtLoadedExecutable& executable) const {
  return {std::nullopt};
}

StatusOr<PjRtDevice*> PjRtCApiClient::LookupDevice(int device_id) const {
  PJRT_Client_LookupDevice_Args args;
  args.struct_size = PJRT_Client_LookupDevice_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.client = c_client_.get();
  args.id = device_id;
  RETURN_STATUS_IF_ERROR(c_api_->PJRT_Client_LookupDevice(&args), c_api_);
  return GetCppDevice(args.device);
}

// Initializes `PJRT_Client_Compile_Args`, which will be used to call
// API PJRT_Client_Compile().
static StatusOr<std::unique_ptr<PjRtLoadedExecutable>> InitializeArgsAndCompile(
    PjRtCApiClient* api_client, const PJRT_Api* c_api, PJRT_Client* client,
    const CompileOptions& options, const std::string& code,
    const std::string& format) {
  PJRT_Client_Compile_Args args;
  args.struct_size = PJRT_Client_Compile_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.client = client;
  TF_ASSIGN_OR_RETURN(const CompileOptionsProto options_proto,
                      options.ToProto());
  std::string options_str = options_proto.SerializeAsString();
  args.compile_options = options_str.c_str();
  args.compile_options_size = options_str.size();

  PJRT_Program program;
  program.struct_size = PJRT_Program_STRUCT_SIZE;
  program.priv = nullptr;
  program.code = code.c_str();
  program.code_size = code.size();
  program.format = format.c_str();
  program.format_size = format.size();
  args.program = &program;

  RETURN_STATUS_IF_ERROR(c_api->PJRT_Client_Compile(&args), c_api);
  std::unique_ptr<PjRtLoadedExecutable> ret =
      std::make_unique<PjRtCApiExecutable>(api_client, args.executable);
  return ret;
}

StatusOr<std::unique_ptr<PjRtLoadedExecutable>> PjRtCApiClient::Compile(
    const XlaComputation& computation, CompileOptions options) {
  std::string module_str = computation.proto().SerializeAsString();
  std::string format(pjrt::kHloFormat);
  return InitializeArgsAndCompile(this, c_api_, c_client_.get(), options,
                                  module_str, format);
}

StatusOr<std::unique_ptr<PjRtLoadedExecutable>> PjRtCApiClient::Compile(
    mlir::ModuleOp module, CompileOptions options) {
  std::string module_bytecode;
  {
    llvm::raw_string_ostream os(module_bytecode);
    mlir::writeBytecodeToFile(module, os);
  }
  std::string format(pjrt::kMlirFormat);
  return InitializeArgsAndCompile(this, c_api_, c_client_.get(), options,
                                  module_bytecode, format);
}

StatusOr<std::string> PjRtCApiClient::SerializeExecutable(
    const PjRtLoadedExecutable& executable) const {
  if (kPjRtCApiBypass) {
    VLOG(1) << "PJRT C API BYPASS: SerializeExecutable";
    return wrapped_->SerializeExecutable(
        *PjRtCApiExecutable::GetWrapped(&executable));
  }
  return Unimplemented("PJRT C API does not support SerializeExecutable");
}

StatusOr<std::unique_ptr<PjRtLoadedExecutable>>
PjRtCApiClient::DeserializeExecutable(absl::string_view serialized,
                                      CompileOptions options) {
  if (kPjRtCApiBypass) {
    VLOG(1) << "PJRT C API BYPASS: DeserializeExecutable";
    return WrapExecutable(wrapped_->DeserializeExecutable(serialized, options));
  }
  return Unimplemented("PJRT C API does not support DeserializeExecutable");
}

StatusOr<std::uintptr_t> PjRtCApiClient::UnsafeBufferPointer(
    PjRtBuffer* buffer) {
  // Validate that the buffer's client matches the function call's client, since
  // that could be a common error.
  // Not doing input nullptr validation since such cases should be rare, and
  // crashes should bubble up the call stack to higher layers. See b/248334153
  // for the considerations that went into this.
  if (buffer->client() != this) {
    return InvalidArgument(
        "buffer passed to PjRtCApiClient::UnsafeBufferPointer() is from a "
        "different client than that of the function call. Buffer's client "
        "platform: '%s', function call's client platform: '%s'.",
        buffer->client()->platform_name(), this->platform_name());
  }

  PJRT_Buffer_UnsafePointer_Args args;
  args.struct_size = PJRT_Buffer_UnsafePointer_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer =
      tensorflow::down_cast<const PjRtCApiBuffer*>(buffer)->c_buffer();

  RETURN_STATUS_IF_ERROR(c_api_->PJRT_Buffer_UnsafePointer(&args), c_api_);

  return args.buffer_pointer;
}

StatusOr<std::unique_ptr<PjRtLoadedExecutable>> PjRtCApiClient::WrapExecutable(
    StatusOr<std::unique_ptr<PjRtLoadedExecutable>> to_wrap) {
  TF_ASSIGN_OR_RETURN(std::unique_ptr<PjRtLoadedExecutable> executable,
                      std::move(to_wrap));
  return std::unique_ptr<PjRtLoadedExecutable>(
      std::make_unique<PjRtCApiExecutable>(this, std::move(executable)));
}

StatusOr<std::unique_ptr<PjRtBuffer>> PjRtCApiClient::WrapBuffer(
    StatusOr<std::unique_ptr<PjRtBuffer>> to_wrap) {
  TF_ASSIGN_OR_RETURN(std::unique_ptr<PjRtBuffer> buffer, std::move(to_wrap));
  return std::unique_ptr<PjRtBuffer>(std::make_unique<PjRtCApiBuffer>(
      this, new PJRT_Buffer{std::move(buffer), pjrt_c_client()}));
}

StatusOr<std::unique_ptr<PjRtBuffer>> PjRtCApiClient::BufferFromHostBuffer(
    const void* data, PrimitiveType type, absl::Span<int64_t const> dims,
    std::optional<absl::Span<int64_t const>> byte_strides,
    HostBufferSemantics host_buffer_semantics,
    std::function<void()> on_done_with_host_buffer, PjRtDevice* device) {
  if (host_buffer_semantics != HostBufferSemantics::kImmutableOnlyDuringCall &&
      host_buffer_semantics != HostBufferSemantics::kZeroCopy &&
      host_buffer_semantics !=
          HostBufferSemantics::kImmutableUntilTransferCompletes) {
    return Unimplemented(
        "PJRT C API does not support HostBufferSemantics other than "
        "HostBufferSemantics::kImmutableOnlyDuringCall, "
        "HostBufferSemantics::kZeroCopy and "
        "HostBufferSemantics::kImmutableUntilTransferCompletes.");
  }

  PJRT_Client_BufferFromHostBuffer_Args args;
  args.struct_size = PJRT_Client_BufferFromHostBuffer_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.client = c_client_.get();
  args.data = data;
  args.type = ::pjrt::ConvertToPjRtBufferType(type);

  args.dims = dims.data();
  args.num_dims = dims.size();
  if (byte_strides.has_value()) {
    args.byte_strides = byte_strides.value().data();
    args.num_byte_strides = byte_strides.value().size();
  } else {
    args.byte_strides = nullptr;
    args.num_byte_strides = 0;
  }
  args.host_buffer_semantics =
      ::pjrt::ConvertToPjRtHostBufferSemantics(host_buffer_semantics);
  args.device = tensorflow::down_cast<PjRtCApiDevice*>(device)->c_device();

  RETURN_STATUS_IF_ERROR(c_api_->PJRT_Client_BufferFromHostBuffer(&args),
                         c_api_);

  auto buffer = std::unique_ptr<PjRtBuffer>(
      std::make_unique<PjRtCApiBuffer>(this, args.buffer));

  std::unique_ptr<PJRT_Event, ::pjrt::PJRT_EventDeleter> event(
      args.done_with_host_buffer, ::pjrt::MakeEventDeleter(c_api_));

  if (on_done_with_host_buffer) {
    PJRT_Event_OnReady_Args event_args;
    event_args.struct_size = PJRT_Event_OnReady_Args_STRUCT_SIZE;
    event_args.priv = nullptr;
    event_args.event = event.get();
    event_args.user_arg = new std::function<void(PJRT_Error*)>(
        [on_done_with_host_buffer = std::move(on_done_with_host_buffer),
         c_api = c_api_](PJRT_Error* error) {
          if (error) {
            ::pjrt::MakeErrorDeleter(c_api)(error);
          }
          on_done_with_host_buffer();
        });
    event_args.callback = [](PJRT_Error* error, void* args) {
      std::function<void(PJRT_Error*)>* on_done_with_host_buffer =
          reinterpret_cast<std::function<void(PJRT_Error*)>*>(args);
      (*on_done_with_host_buffer)(error);
      delete on_done_with_host_buffer;
    };

    RETURN_STATUS_IF_ERROR(c_api_->PJRT_Event_OnReady(&event_args), c_api_);
  }

  return buffer;
}

const PJRT_Api* PjRtCApiClient::pjrt_c_api() const { return c_api_; }

// --------------------------------- Devices -----------------------------------

PjRtCApiDevice::PjRtCApiDevice(PJRT_Device* device, PjRtCApiClient* client)
    : client_(client), device_(device) {
  wrapped_ = device_->device;
  InitAttributes();
}

PjRtClient* PjRtCApiDevice::client() const { return client_; }

int PjRtCApiDevice::id() const {
  PJRT_Device_Id_Args args;
  args.struct_size = PJRT_Device_Id_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Device_Id(&args), api);
  return args.id;
}

int PjRtCApiDevice::process_index() const {
  PJRT_Device_ProcessIndex_Args args;
  args.struct_size = PJRT_Device_ProcessIndex_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Device_ProcessIndex(&args), api);
  return args.process_index;
}

bool PjRtCApiDevice::IsAddressable() const {
  PJRT_Device_IsAddressable_Args args;
  args.struct_size = PJRT_Device_IsAddressable_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Device_IsAddressable(&args), api);
  return args.is_addressable;
}

void PjRtCApiDevice::InitAttributes() {
  attributes_ = {};
  PJRT_Device_Attributes_Args args;
  args.struct_size = PJRT_Device_Attributes_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Device_Attributes(&args), api);

  for (int i = 0; i < args.num_attributes; ++i) {
    const auto& attribute = args.attributes[i];
    std::string attribute_name(attribute.name, attribute.name_size);
    switch (attribute.type) {
      case PJRT_Device_Attribute::PJRT_Device_Attribute_kString: {
        std::string string_value(attribute.string_value, attribute.value_size);
        attributes_[attribute_name] = PjRtDeviceAttribute(string_value);
        break;
      }
      case PJRT_Device_Attribute::PJRT_Device_Attribute_kInt64: {
        attributes_[attribute_name] =
            PjRtDeviceAttribute(attribute.int64_value);
        break;
      }
      case PJRT_Device_Attribute::PJRT_Device_Attribute_kInt64List: {
        const int64_t* array_ptr(attribute.int64_array_value);
        std::vector<int64_t> int64_array(array_ptr,
                                         array_ptr + attribute.value_size);
        attributes_[attribute_name] = PjRtDeviceAttribute(int64_array);
        break;
      }
    }
  }
}

const absl::flat_hash_map<std::string, PjRtDeviceAttribute>&
PjRtCApiDevice::Attributes() const {
  return attributes_;
}

absl::string_view PjRtCApiDevice::device_kind() const {
  PJRT_Device_Kind_Args args;
  args.struct_size = PJRT_Device_Kind_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;

  const PJRT_Api* c_api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(c_api->PJRT_Device_Kind(&args), c_api);

  absl::string_view device_kind(args.device_kind, args.device_kind_size);
  return device_kind;
}

int PjRtCApiDevice::local_hardware_id() const {
  PJRT_Device_LocalHardwareId_Args args;
  args.struct_size = PJRT_Device_LocalHardwareId_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Device_LocalHardwareId(&args), api);
  return args.local_hardware_id;
}

absl::string_view PjRtCApiDevice::DebugString() const {
  PJRT_Device_DebugString_Args args;
  args.struct_size = PJRT_Device_DebugString_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* c_api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(c_api->PJRT_Device_DebugString(&args), c_api);
  absl::string_view debug_string(args.debug_string, args.debug_string_size);
  return debug_string;
}

absl::string_view PjRtCApiDevice::ToString() const {
  PJRT_Device_ToString_Args args;
  args.struct_size = PJRT_Device_ToString_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.device = device_;
  const PJRT_Api* c_api = client_->pjrt_c_api();
  pjrt::LogFatalIfPjrtError(c_api->PJRT_Device_ToString(&args), c_api);
  absl::string_view to_string(args.to_string, args.to_string_size);
  return to_string;
}

// ------------------------------- Executables ---------------------------------

PjRtCApiExecutable::PjRtCApiExecutable(
    PjRtCApiClient* client, std::unique_ptr<PjRtLoadedExecutable> wrapped)
    : PjRtCApiExecutable(client, new PJRT_Executable{std::move(wrapped),
                                                     client->pjrt_c_client()}) {
}

PjRtCApiExecutable::PjRtCApiExecutable(PjRtCApiClient* client,
                                       PJRT_Executable* executable)
    : client_(client),
      executable_(executable,
                  ::pjrt::MakeExecutableDeleter(client->pjrt_c_api())) {
  InitDevices();
}

void PjRtCApiExecutable::InitDevices() {
  PJRT_Executable_AddressableDevices_Args args;
  args.struct_size = PJRT_Executable_AddressableDevices_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.executable = executable_.get();
  args.addressable_devices = nullptr;
  args.num_addressable_devices = 0;

  const PJRT_Api* api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Executable_AddressableDevices(&args),
                            api);

  const size_t num_addressable_devices = args.num_addressable_devices;
  addressable_devices_.reserve(num_addressable_devices);

  for (size_t i = 0; i < num_addressable_devices; ++i) {
    PJRT_Device* device = args.addressable_devices[i];
    PjRtCApiDevice* c_api_device = client_->GetCppDevice(device);
    addressable_devices_.push_back(c_api_device);
  }
}

static std::vector<std::vector<PJRT_Buffer*>> Convert2DCppBuffersToCBuffers(
    absl::Span<const std::vector<PjRtBuffer*>> cpp_lists) {
  std::vector<std::vector<PJRT_Buffer*>> c_lists;
  c_lists.reserve(cpp_lists.size());
  for (const auto& cpp_list : cpp_lists) {
    auto& c_list = c_lists.emplace_back();
    c_list.reserve(cpp_list.size());
    for (PjRtBuffer* buffer : cpp_list) {
      auto* c_api_argument = tensorflow::down_cast<PjRtCApiBuffer*>(buffer);
      c_list.push_back(c_api_argument->c_buffer());
    }
  }
  return c_lists;
}

static std::vector<std::vector<std::unique_ptr<PjRtBuffer>>>
Convert2DCBuffersToCppBuffers(PJRT_Buffer*** c_lists, size_t outer_size,
                              int inner_size, xla::PjRtCApiClient* client) {
  std::vector<std::vector<std::unique_ptr<PjRtBuffer>>> ret;
  for (size_t i = 0; i < outer_size; ++i) {
    auto& output_list = ret.emplace_back();
    output_list.reserve(inner_size);
    for (size_t j = 0; j < inner_size; ++j) {
      output_list.push_back(
          std::make_unique<PjRtCApiBuffer>(client, c_lists[i][j]));
    }
  }
  return ret;
}

// Create and return a `PjRtFuture` with a promise which will be set when
// `PJRT_Event` is ready. This also deletes the input `PJRT_Event` on the
// callback.
static xla::PjRtFuture<Status> ConvertCEventToCppFuture(PJRT_Event* c_future,
                                                        const PJRT_Api* c_api) {
  PJRT_Event_OnReady_Args event_onready_args;
  event_onready_args.struct_size = PJRT_Event_OnReady_Args_STRUCT_SIZE;
  event_onready_args.priv = nullptr;
  event_onready_args.event = c_future;

  PjRtFuture<Status>::Promise promise = PjRtFuture<Status>::CreatePromise();
  event_onready_args.user_arg = new std::function<void(PJRT_Error*)>(
      [promise, c_future, c_api](PJRT_Error* error) mutable {
        if (error != nullptr) {
          xla::Status s = ::pjrt::PjrtErrorToStatus(error, c_api);
          promise.Set(s);
          ::pjrt::MakeErrorDeleter(c_api)(error);
        } else {
          promise.Set(tsl::OkStatus());
        }
        ::pjrt::MakeEventDeleter(c_api)(c_future);
      });
  event_onready_args.callback = [](PJRT_Error* error, void* arg) {
    std::function<void(PJRT_Error*)>* set_future =
        reinterpret_cast<std::function<void(PJRT_Error*)>*>(arg);
    (*set_future)(error);
    delete set_future;
  };

  std::unique_ptr<PJRT_Error> error(
      c_api->PJRT_Event_OnReady(&event_onready_args));
  if (error != nullptr) {
    xla::Status s = ::pjrt::PjrtErrorToStatus(error.get(), c_api);
    return PjRtFuture<Status>(s);
  }
  return PjRtFuture<Status>(std::move(promise));
}

xla::StatusOr<PJRT_Executable_Execute_Args>
PjRtCApiExecutable::GetCommonExecuteArgs(
    absl::Span<const std::vector<PjRtBuffer*>> argument_handles,
    const ExecuteOptions& options, PJRT_ExecuteOptions& c_options,
    std::vector<std::vector<PJRT_Buffer*>>& c_argument_lists_storage,
    std::vector<PJRT_Buffer**>& c_arguments,
    std::vector<std::vector<PJRT_Buffer*>>& c_output_lists_storage,
    std::vector<PJRT_Buffer**>& c_output_lists) {
  PJRT_Executable_Execute_Args args;
  args.struct_size = PJRT_Executable_Execute_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.executable = executable_.get();
  args.options = &c_options;
  args.options->struct_size = PJRT_ExecuteOptions_STRUCT_SIZE;
  args.options->launch_id = options.launch_id;
  args.num_devices = argument_handles.size();
  CHECK_GT(args.num_devices, 0);
  args.num_args = argument_handles[0].size();

  // Populates `args.argument_lists` from `argument_handles`.
  c_argument_lists_storage = Convert2DCppBuffersToCBuffers(argument_handles);
  c_arguments.reserve(c_argument_lists_storage.size());
  for (auto& argument_list : c_argument_lists_storage) {
    c_arguments.push_back(argument_list.data());
  }
  args.argument_lists = c_arguments.data();

  // Allocates memory for output. `c_buffer_lists_storage` and `c_buffer_lists`
  // needs to stay alive during the call of `PJRT_Executable_Execute`.

  PJRT_Executable_NumOutputs_Args numoutputs_args;
  numoutputs_args.struct_size = PJRT_Executable_NumOutputs_Args_STRUCT_SIZE;
  numoutputs_args.priv = nullptr;
  numoutputs_args.executable = executable_.get();
  RETURN_STATUS_IF_ERROR(
      pjrt_c_api()->PJRT_Executable_NumOutputs(&numoutputs_args), pjrt_c_api());
  size_t outer_size = args.num_devices;
  size_t inner_size = numoutputs_args.num_outputs;
  c_output_lists_storage.resize(outer_size);
  c_output_lists.resize(outer_size);
  for (int i = 0; i < outer_size; ++i) {
    c_output_lists_storage[i].resize(inner_size);
    c_output_lists[i] = c_output_lists_storage[i].data();
  }
  args.output_lists = c_output_lists.data();

  return args;
}

StatusOr<std::vector<std::vector<std::unique_ptr<PjRtBuffer>>>>
PjRtCApiExecutable::Execute(
    absl::Span<const std::vector<PjRtBuffer*>> argument_handles,
    const ExecuteOptions& options,
    std::optional<std::vector<PjRtFuture<Status>>>& returned_futures) {
  std::vector<std::vector<PJRT_Buffer*>> c_argument_lists_storage;
  std::vector<std::vector<PJRT_Buffer*>> c_output_lists_storage;
  std::vector<PJRT_Buffer**> c_output_lists;
  PJRT_ExecuteOptions c_options;
  std::vector<PJRT_Buffer**> c_arguments;
  TF_ASSIGN_OR_RETURN(
      PJRT_Executable_Execute_Args args,
      GetCommonExecuteArgs(argument_handles, options, c_options,
                           c_argument_lists_storage, c_arguments,
                           c_output_lists_storage, c_output_lists));

  args.execute_device = nullptr;
  args.device_complete_events = nullptr;
  if (returned_futures.has_value()) {
    std::vector<PJRT_Event*> c_events(args.num_devices);
    args.device_complete_events = c_events.data();
  }

  RETURN_STATUS_IF_ERROR(pjrt_c_api()->PJRT_Executable_Execute(&args),
                         pjrt_c_api());

  if (returned_futures.has_value()) {
    returned_futures->resize(args.num_devices);
    for (int i = 0; i < returned_futures->size(); ++i) {
      (*returned_futures)[i] = ConvertCEventToCppFuture(
          args.device_complete_events[i], pjrt_c_api());
    }
  }

  return Convert2DCBuffersToCppBuffers(args.output_lists, args.num_devices,
                                       c_output_lists_storage[0].size(),
                                       client_);
}

StatusOr<std::vector<std::unique_ptr<PjRtBuffer>>>
PjRtCApiExecutable::ExecuteSharded(
    absl::Span<PjRtBuffer* const> argument_handles, PjRtDevice* device,
    const ExecuteOptions& options,
    std::optional<PjRtFuture<Status>>& returned_future, bool fill_future) {
  if (fill_future) {
    return Unimplemented(
        "PJRT C API does not support fill_future for ExecuteSharded");
  }
  std::vector<std::vector<PjRtBuffer*>> argument_handles_vec = {
      {argument_handles.begin(), argument_handles.end()}};

  std::vector<std::vector<PJRT_Buffer*>> c_argument_lists_storage;
  std::vector<std::vector<PJRT_Buffer*>> c_output_lists_storage;
  std::vector<PJRT_Buffer**> c_output_lists;
  PJRT_ExecuteOptions c_options;
  std::vector<PJRT_Buffer**> c_arguments;
  TF_ASSIGN_OR_RETURN(
      PJRT_Executable_Execute_Args args,
      GetCommonExecuteArgs(argument_handles_vec, options, c_options,
                           c_argument_lists_storage, c_arguments,
                           c_output_lists_storage, c_output_lists));

  args.execute_device =
      tensorflow::down_cast<PjRtCApiDevice*>(device)->c_device();

  RETURN_STATUS_IF_ERROR(pjrt_c_api()->PJRT_Executable_Execute(&args),
                         pjrt_c_api());

  return std::move(Convert2DCBuffersToCppBuffers(
      args.output_lists, args.num_devices, c_output_lists_storage[0].size(),
      client_)[0]);
}

StatusOr<std::vector<std::unique_ptr<PjRtBuffer>>>
PjRtCApiExecutable::ExecutePortable(
    absl::Span<PjRtBuffer* const> argument_handles, PjRtDevice* device,
    const ExecuteOptions& options,
    std::optional<PjRtFuture<Status>>& returned_future, bool fill_future) {
  if (kPjRtCApiBypass) {
    VLOG(1) << "PJRT C API BYPASS: ExecutePortable";
    std::vector<PjRtBuffer*> wrapped_args =
        PjRtCApiBuffer::GetWrappedVector(argument_handles);

    TF_ASSIGN_OR_RETURN(std::vector<std::unique_ptr<PjRtBuffer>> out,
                        wrapped()->ExecutePortable(
                            wrapped_args, PjRtCApiDevice::GetWrapped(device),
                            options, returned_future, fill_future));

    for (std::unique_ptr<PjRtBuffer>& buffer : out) {
      buffer = std::make_unique<PjRtCApiBuffer>(
          client_,
          new PJRT_Buffer{std::move(buffer), client_->pjrt_c_client()});
    }
    return out;
  }
  return Unimplemented("PJRT C API does not support ExecutePortable");
}

PjRtLoadedExecutable* PjRtCApiExecutable::wrapped() const {
  return executable_->executable.get();
}

absl::string_view PjRtCApiExecutable::name() const {
  const PJRT_Api* c_api = pjrt_c_api();
  PJRT_Executable_Name_Args args;
  args.executable = executable_.get();
  args.struct_size = PJRT_Executable_Name_Args_STRUCT_SIZE;
  args.priv = nullptr;
  pjrt::LogFatalIfPjrtError(c_api->PJRT_Executable_Name(&args), c_api);

  absl::string_view executable_name(args.executable_name,
                                    args.executable_name_size);
  return executable_name;
}

void PjRtCApiExecutable::Delete() {
  PJRT_Executable_Delete_Args args;
  args.struct_size = PJRT_Executable_Delete_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.executable = executable_.get();
  const PJRT_Api* c_api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(c_api->PJRT_Executable_Delete(&args), c_api);
}

bool PjRtCApiExecutable::IsDeleted() {
  PJRT_Executable_IsDeleted_Args args;
  args.struct_size = PJRT_Executable_IsDeleted_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.executable = executable_.get();

  const PJRT_Api* c_api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(c_api->PJRT_Executable_IsDeleted(&args), c_api);
  return args.is_deleted;
}

int64_t PjRtCApiExecutable::SizeOfGeneratedCodeInBytes() const {
  PJRT_Executable_SizeOfGeneratedCodeInBytes_Args args;
  args.struct_size =
      PJRT_Executable_SizeOfGeneratedCodeInBytes_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.executable = executable_.get();

  const PJRT_Api* c_api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(
      c_api->PJRT_Executable_SizeOfGeneratedCodeInBytes(&args), c_api);
  return args.size_in_bytes;
}

// ---------------------------------- Buffers ----------------------------------

PjRtCApiBuffer::PjRtCApiBuffer(PjRtCApiClient* client, PJRT_Buffer* buffer)
    : client_(client),
      buffer_(buffer, ::pjrt::MakeBufferDeleter(client->pjrt_c_api())),
      readiness_event_(nullptr, ::pjrt::MakeEventDeleter(client->pjrt_c_api())),
      wrapped_(buffer_->buffer.get()) {
  set_shape();
}

const Shape& PjRtCApiBuffer::on_device_shape() const {
  CHECK(shape_.has_value())
      << "Shape should be initialized in PjRtCApiBuffer constructor.";
  return shape_.value();
}

void PjRtCApiBuffer::set_shape() {
  PJRT_Buffer_OnDeviceTrimmedShape_Args args;
  args.struct_size = PJRT_Buffer_OnDeviceTrimmedShape_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer = buffer_.get();

  pjrt::LogFatalIfPjrtError(
      client_->pjrt_c_api()->PJRT_Buffer_OnDeviceTrimmedShape(&args),
      client_->pjrt_c_api());

  xla::PrimitiveType element_type =
      static_cast<xla::PrimitiveType>(args.element_type);

  CHECK_NE(element_type, xla::PrimitiveType::TUPLE);

  absl::Span<const int64_t> dims = ApiConverter::MakeSpan(args.dimensions);
  absl::Span<const bool> dynamic_dims =
      ApiConverter::MakeSpan(args.dynamic_dimensions);

  Shape trimmed_shape = Shape(element_type, dims, dynamic_dims, {});

  if (args.has_layout) {
    *(trimmed_shape.mutable_layout()) = ApiConverter::FromC(&args.layout);
  }

  shape_ = trimmed_shape;

  // TODO(amangu): Refactor the deletion.
  if (args.dimensions.size > TPU_C_API_MAX_INLINED) {
    delete[] args.dimensions.heap;
  }

  if (args.dynamic_dimensions.size > TPU_C_API_MAX_INLINED) {
    delete[] args.dynamic_dimensions.heap;
  }

  if (args.has_layout) {
    if (args.layout.minor_to_major.size > TPU_C_API_MAX_INLINED) {
      delete[] args.layout.minor_to_major.heap;
    }

    if (args.layout.tiles.size > TPU_C_API_MAX_INLINED) {
      delete[] args.layout.tiles.heap;
    }
  }
}

PjRtFuture<Status> PjRtCApiBuffer::ToLiteral(MutableLiteralBase* literal) {
  PJRT_Buffer_ToHostBuffer_Args args;
  args.struct_size = PJRT_Buffer_ToHostBuffer_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.src = buffer_.get();

  const xla::Shape& shape = literal->shape();

  if (!shape.IsArray()) {
    return PjRtFuture<Status>(
        Unimplemented("PjRtCApiBuffer::ToLiteral: Shapes other than array are"
                      "not supported."));
  }

  args.dst_size = ShapeUtil::ByteSizeOfElements(shape);
  args.dst = literal->untyped_data();

  std::unique_ptr<PJRT_Error, ::pjrt::PJRT_ErrorDeleter> error{
      pjrt_c_api()->PJRT_Buffer_ToHostBuffer(&args),
      ::pjrt::MakeErrorDeleter(pjrt_c_api())};

  if (error != nullptr) {
    xla::Status s = ::pjrt::PjrtErrorToStatus(error.get(), pjrt_c_api());
    return PjRtFuture<Status>(s);
  }

  PJRT_Event_OnReady_Args event_onready_args;
  event_onready_args.struct_size = PJRT_Event_OnReady_Args_STRUCT_SIZE;
  event_onready_args.priv = nullptr;
  event_onready_args.event = args.event;

  PjRtFuture<Status>::Promise promise = PjRtFuture<Status>::CreatePromise();

  event_onready_args.user_arg = new std::function<void(PJRT_Error*)>(
      [promise, api = client_->pjrt_c_api(),
       pjrt_event = args.event](PJRT_Error* error) mutable {
        if (error) {
          xla::Status s = ::pjrt::PjrtErrorToStatus(error, api);
          promise.Set(s);
          ::pjrt::MakeErrorDeleter(api)(error);
        } else {
          promise.Set(OkStatus());
        }
        ::pjrt::MakeEventDeleter(api)(pjrt_event);
      });

  event_onready_args.callback = [](PJRT_Error* error, void* args) {
    std::function<void(PJRT_Error*)>* set_future =
        reinterpret_cast<std::function<void(PJRT_Error*)>*>(args);
    (*set_future)(error);
    delete set_future;
  };

  error.reset(pjrt_c_api()->PJRT_Event_OnReady(&event_onready_args));

  if (error != nullptr) {
    xla::Status s = ::pjrt::PjrtErrorToStatus(error.get(), pjrt_c_api());
    return PjRtFuture<Status>(s);
  }

  PjRtFuture<Status> future = PjRtFuture<Status>(std::move(promise));

  return future;
}

StatusOr<size_t> PjRtCApiBuffer::GetOnDeviceSizeInBytes() const {
  PJRT_Buffer_OnDeviceSizeInBytes_Args args;
  args.struct_size = PJRT_Buffer_OnDeviceSizeInBytes_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer = buffer_.get();
  RETURN_STATUS_IF_ERROR(
      client_->pjrt_c_api()->PJRT_Buffer_OnDeviceSizeInBytes(&args),
      client_->pjrt_c_api());

  return args.on_device_size_in_bytes;
}

PjRtDevice* PjRtCApiBuffer::device() const {
  PJRT_Buffer_Device_Args args;
  args.struct_size = PJRT_Buffer_Device_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer = buffer_.get();
  const PJRT_Api* api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Buffer_Device(&args), api);
  return client_->GetCppDevice(args.device);
}

void PjRtCApiBuffer::Delete() {
  PJRT_Buffer_Delete_Args args;
  args.struct_size = PJRT_Buffer_Delete_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer = buffer_.get();
  const PJRT_Api* api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Buffer_Delete(&args), api);
}

bool PjRtCApiBuffer::IsDeleted() {
  PJRT_Buffer_IsDeleted_Args args;
  args.struct_size = PJRT_Buffer_IsDeleted_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer = buffer_.get();
  const PJRT_Api* api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Buffer_IsDeleted(&args), api);
  return args.is_deleted;
}

StatusOr<std::unique_ptr<PjRtBuffer>> PjRtCApiBuffer::CopyToDevice(
    PjRtDevice* dst_device) {
  if (dst_device->client() == client_) {
    PJRT_Buffer_CopyToDevice_Args args;
    args.struct_size = PJRT_Buffer_CopyToDevice_Args_STRUCT_SIZE;
    args.priv = nullptr;
    args.buffer = buffer_.get();
    args.dst_device =
        tensorflow::down_cast<PjRtCApiDevice*>(dst_device)->c_device();
    const PJRT_Api* api = pjrt_c_api();
    RETURN_STATUS_IF_ERROR(api->PJRT_Buffer_CopyToDevice(&args), api);
    return std::unique_ptr<PjRtBuffer>(
        std::make_unique<PjRtCApiBuffer>(client_, args.dst_buffer));
  } else {
    // Copy across PjRtClients by copying through host
    TF_ASSIGN_OR_RETURN(std::shared_ptr<Literal> literal, ToLiteralSync());
    absl::InlinedVector<int64_t, 4> byte_strides(
        literal->shape().dimensions_size());
    TF_RETURN_IF_ERROR(
        ShapeUtil::ByteStrides(literal->shape(), absl::MakeSpan(byte_strides)));
    // Avoid use-after-free on `literal` due to unsequenced move and use.
    Literal* literal_pointer = literal.get();
    return dst_device->client()->BufferFromHostBuffer(
        literal_pointer->untyped_data(),
        literal_pointer->shape().element_type(),
        literal_pointer->shape().dimensions(), byte_strides,
        PjRtClient::HostBufferSemantics::kZeroCopy,
        [literal{std::move(literal)}]() { /* frees literal */ }, dst_device);
  }
}

bool PjRtCApiBuffer::IsOnCpu() const {
  PJRT_Buffer_IsOnCpu_Args args;
  args.struct_size = PJRT_Buffer_IsOnCpu_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.buffer = buffer_.get();
  const PJRT_Api* api = pjrt_c_api();
  pjrt::LogFatalIfPjrtError(api->PJRT_Buffer_IsOnCpu(&args), api);
  return args.is_on_cpu;
}

PJRT_Event* PjRtCApiBuffer::GetReadyEvent() {
  if (readiness_event_ == nullptr) {
    const PJRT_Api* api = pjrt_c_api();
    PJRT_Buffer_ReadyEvent_Args args;
    args.struct_size = PJRT_Buffer_ReadyEvent_Args_STRUCT_SIZE;
    args.priv = nullptr;
    args.buffer = buffer_.get();
    pjrt::LogFatalIfPjrtError(api->PJRT_Buffer_ReadyEvent(&args), api);
    readiness_event_.reset(args.event);
  }
  return readiness_event_.get();
}

void PjRtCApiBuffer::MakePromiseTrackEvent() {
  CHECK(readiness_promise_ != nullptr);
  const PJRT_Api* api = pjrt_c_api();
  PJRT_Event_OnReady_Args args;
  args.struct_size = PJRT_Event_OnReady_Args_STRUCT_SIZE;
  args.priv = nullptr;
  args.event = GetReadyEvent();
  args.user_arg = new std::function<void(PJRT_Error*)>(
      [promise = readiness_promise_, api](PJRT_Error* error) -> void {
        Status status = ::pjrt::PjrtErrorToStatus(error, api);
        promise->Set(status);
        ::pjrt::MakeErrorDeleter(api)(error);
      });
  args.callback = [](PJRT_Error* error, void* callback_ptr) {
    auto callback =
        static_cast<std::function<void(PJRT_Error*)>*>(callback_ptr);
    CHECK(callback != nullptr);
    (*callback)(error);
    delete callback;
  };

  std::unique_ptr<PJRT_Error, ::pjrt::PJRT_ErrorDeleter> error{
      api->PJRT_Event_OnReady(&args), ::pjrt::MakeErrorDeleter(api)};
  if (error != nullptr) {
    readiness_promise_->Set(::pjrt::PjrtErrorToStatus(error.get(), api));
  }
}

PjRtFuture<Status> PjRtCApiBuffer::GetReadyFuture() {
  if (readiness_promise_ == nullptr) {
    readiness_promise_ = std::make_shared<PjRtFuture<Status>::Promise>(
        PjRtFuture<Status>::CreatePromise());
    MakePromiseTrackEvent();
  }
  return PjRtFuture<Status>{*readiness_promise_};
}

// -------------------------------- API access ---------------------------------

StatusOr<std::unique_ptr<PjRtClient>> GetCApiClient(
    absl::string_view device_type) {
#if !defined(PLATFORM_GOOGLE) || defined(LIBTPU_STATIC)
  TF_RETURN_IF_ERROR(tensorflow::tpu::FindAndLoadTpuLibrary());
#endif
  TF_ASSIGN_OR_RETURN(const PJRT_Api* c_api,
                      stream_executor::tpu::PjrtApi(device_type));
  if (c_api == nullptr) {
    return InternalError("PJRT C API is nullptr");
  }

  PJRT_Client_Create_Args init_args;
  init_args.struct_size = PJRT_Client_Create_Args_STRUCT_SIZE;
  init_args.priv = nullptr;
  RETURN_STATUS_IF_ERROR(c_api->PJRT_Client_Create(&init_args), c_api);
  PJRT_Client* c_client = init_args.client;

  return std::unique_ptr<PjRtClient>(
      std::make_unique<PjRtCApiClient>(c_api, c_client));
}

}  // namespace xla

redpajama_set_name: RedPajamaGithub


text:
About Michael H. Dickman
Originally from Cincinnati, Michael has a Ph.D. in chemistry from the University of California at Irvine, and a law degree from Franklin Pierce Law Center in Concord, New Hampshire. He has also lived in the Washington, DC area, and Bremen, Germany. Currently residing in LV, Michael's interests include games and puzzles, computer programming, science, cooking, and ceramics.
July 2, 2011 Michael H. Dickman
Nepal Tasting and the Exhibit Room
Some excellent Nepal black teas are graded 'SFTGFOP' and some other truly remarkable facts were uncovered at this year's Tea Expo at the Las Vegas Convention Center
June 29, 2011 Michael H. Dickman
World Tea Expo 2011
Hot or iced, there's black tea and green tea, and oolong in between. There's tea from China and tea from India, from Sri Lanka and Taiwan and much more exciting news from this year's Tea Expo
April 18, 2011 Michael H. Dickman
Las Vegas Science Festival 2011
'Science in Vegas: What are the Odds?' is a new festival for kids of all ages!
February 16, 2010 Michael H. Dickman
A Nerd in Vegas: Smith Center for the Performing Arts
February 10th at the Fifth Street School auditorium, the topic under discussion was nothing less than the transformation of Las Vegas culture by building a world-class performing arts venue.
January 26, 2010 Michael H. Dickman
Nerd in Vegas: Cord Blood America Comes to Vegas
Cord Blood America, Inc. has one of the largest stem cell cryogenic storage facilities in the nation, here in Vegas

redpajama_set_name: RedPajamaCommonCrawl


text:
[ January 16, 2021 ] Transforming FinTech, Healthcare, And More	Blockchain
[ January 16, 2021 ] Trader Luke Martin Says These Altcoins Will Outperform Bitcoin and Become Top Crypto Assets of 2021	Altcoin
[ January 16, 2021 ] A man has over $200 million worth of Bitcoin, but he forgot the password to access it	Bitcoin
[ January 16, 2021 ] Over $400 Million Now Staked as Part of Ethereum 2.0 Staking Service Offered by Digital Assets Exchange Kraken	Ethereum
HomeRippleRipple On Bearish Momentum: 7.97% Down In The Last 6 Hours
Ripple On Bearish Momentum: 7.97% Down In The Last 6 Hours
December 31, 2020 John Ripple 0
Ripple is currently on bearish momentum. At 15:03 EST on Wed 23 Dec, Ripple is at $0.31 and down by 7.97% in the last 6 hours.
Ripple Range
Over the last six hours, Ripple's higher value was $0.34 and the lower value was $0.30.
Over the last twelve hours, Ripple's higher value was $0.36 and the lower value was $0.30.
In relation to Ripple's daily highs and lows, it's 4.533% up from its trailing 24-hour low of $0.30 and 31.826% down from its trailing 24-hour high of $0.46.
Concerning Ripple's yearly highs and lows, it's 172.459% up from its 52-week low and 59.167% down from its 52-week high.
Last news about Ripple
Ripple to face SEC suit over XRP cryptocurrency. According to The Wall Street Journal on Tue Dec 22, "Ripple had a $10 billion valuation in its most recent funding round in 2019, and XRP is the third-largest cryptocurrency by market value.", "None of those companies, though, was as big as Ripple and XRP. "
Cryptocurrency firm ripple expects to be sued by the sec; XRP plunges. According to CNBC on Tue Dec 22, "Ripple, the fintech company best known for cryptocurrency XRP, has said it expects to be sued by the Securities and Exchange Commission over allegations that it violated investor protection laws.", "Though it claims to be independent of the cryptocurrency, Ripple owns 55 billion of the total 100 billion XRP tokens in existence. "
Ripple says it faces SEC lawsuit as cryptocurrency XRP drops. According to Bloomberg Quint on Tue Dec 22, "XRP, the world's third-largest cryptocurrency, slumped after Ripple Labs Inc. said it faces a U.S. Securities and Exchange Commission lawsuit over its affiliated token.", "Ripple will challenge the suit in the courts "to get clear rules of the road for the entire industry in the U.S.," he added."
Ripple labs, executives sued by SEC for failing to register XRP. According to Bloomberg Quint on Tue Dec 22, "Ripple will challenge the suit in the courts "to get clear rules of the road for the entire industry in the U.S.," Garlinghouse said.", "On Monday, the CEO disclosed that the regulators had "inexplicably decided to sue Ripple" but he didn't specify the nature of the allegations. "
US regulator charges ripple over its XRP asset, saying it's a $1.3 billion unregistered offering, not a cryptocurrency. According to Business Insider on Wed Dec 23, ""To be clear, this is all based on their illogical claim that XRP is, in their view, somehow the functional equivalent of a share of stock," Garlinghouse wrote on Ripple's company blog.", "Two of Ripple's lawyers on Tuesday said the SEC's suit was without merit."
High-flying crypto fund dumps XRP with ripple in SEC 'hot water'. According to Bloomberg Quint on Wed Dec 23, ""Ripple also risks a court ruling that XRP is a security, which would subject it to stricter SEC rules that may curb transactions as U.S. virtual marketplaces may be reluctant to list XRP due to the risk of facilitating the sale of a potentially unregistered security."", "Unlike Bitcoin or Ether — which the SEC considers currencies and are decentralized — XRP's value was mainly linked to Ripple products, with the firm attempting to influence supply and demand for the token, the analysts wrote."
News about Bitcoin
Elon Musk inquired on twitter about 'large' Bitcoin transactions after a crypto booster suggested he convert Tesla's balance sheet. According to Business Insider on Mon Dec 21, "Before the exchange with Saylor, he tweeted "Bitcoin is my safe word," but then followed up by saying, "Just kidding, who needs a safe word anyway!?"", "Following the Saylor conversation, Musk tweeted: "Bitcoin is almost as bs as fiat money," and then suggested to his followers he's a fan of Dogecoin, a parody cryptocurrency."
Bitcoin Custody May Have Arrived, But Here Is What To Look Out For
Transforming FinTech, Healthcare, And More
A man has over $200 million worth of Bitcoin, but he forgot the password to access it
Over $400 Million Now Staked as Part of Ethereum 2.0 Staking Service Offered by Digital Assets Exchange Kraken
After a successful launch of $500mil liquidity, SashimiSwap unveils its new strategy and Roadmap
Can Ethereum & Blockchain Technology Help Answer Censorship Issues?
Ripple CTO shares 'incredibly encouraging' results for XRPL optimization
CoinDesk Live Recap: Co-Founders Revisit Ethereum's Launch Drama
Tetragon Sues Ripple to Force Stock Redemption
Performance Art Film Is Now Tokenized on the Ethereum Blockchain
Blockchain Week in Review – July 2020 #3 | Perkins Coie


We've rounded up the best cycling in Belchamp Walter in our quest to discover brilliant family attractions and places to visit near you. There are 2 Belchamp Walter cycling to pick from. Alternatively, why not explore some other sports and activities days out nearby, including cinemas and theatres, arts and crafts or paintballing. Find the perfect places to go with your kids and get out on your next adventure!
If you've visited one of these cycling in Belchamp Walter , please consider leaving a review on the attraction page to help others plan their next fun day out.


Please join me at the 35th Annual Austin Music Awards. I am happy to host and manage the "Louis&Nick Lounge" ths year in our new venue. It might just be the best show yet! Stay tuned and buy your tickets today!
The Austin Chronicle, SXSW, and Stratus Properties at the Moody Theater are proud to present the 35th annual Austin Music Awards on Sunday, March 12, 2017 at ACL Live at the Moody Theater, with proceeds benefiting the SIMS Foundation.
With a new date and new venue for 2017, the Austin Music Awards will continue in the hallowed tradition of celebrating winners from the Austin Chronicle Music Poll while continuing to be a unique and innovative force on Austin's music scene.
New this year, the Mayor's Office will proudly support the Austin Music Awards by sponsoring the AMA artists along with the new "Mayor's House Band" – led by returning Music Director Charlie Sexton.
Stay tuned for lineup announcements here and on our Facebook event!
Thanks to SXSW, Arts + Labor, KUTX, Stratus Properties, and the SIMS Foundation.


Pokey went to her friend Brooke's birthday party tonight. She would be the one in back with the glow in the dark goggles. The only one with goggles. I'm glad she was invited because now that her Dad has accepted a job in Arkansas a move is inevitable. She has been a good friend to Pokey and I know she'll be missed.
Little Man completed his Bear Badge and started Webelos this week.
Little Man will end up with some good scars on his hand from his scooter crash. Not great for my family picture plan for next week. It might have to be postponed a little.
3 frogs, 2 butterflies, and 1 katydid were all captured via Little Man's net this week.
Haldan passed his 1st of three final exams for his senior reactor operator program. It was a week long exam that included both performance and written portions. The next two matter substantially and are job dependent. He's been putting in tons of study hours, but I'm sure he could use your thoughts and prayers. They are next week and the last week of September (if he passes the second one).
Little Man got $40 for his birthday and is dead set on getting a guinea pig. Heaven help us all. I've tried to sway him, but can't think of another pet that is interactive and smells any better. I have a feeling "G-Force" was a contributing factor.
Lost Pokey for about 45 minutes this week. The missionaries were in the area and helped find her.
Only one week of summer left!
I'll be sad to see the Jarbo's go, but I am glad that Jason found something. Where was Camille? Good luck with the guinea pig, and good luck to Haldan on his exams.


Birdorable.com welcomes the American Oystercatcher to the Birdorable family of cute birds. This unique bird is marked by its black and white body and a long, thick orange beak. They use this large and heavy beak to pry open molluscs. The American Oystercatcher is found on the Atlantic coast of North America from New England to northern Florida, where it is also found on the Gulf coast. It is very similar to the Eurasian Oystercatcher, which is very numerous around Europe and Asia.
1 comment on "Birdorable American Oystercatcher"


text:
Insiders Freezing Out Challengers
Yours for democracy, Mike Hersh for Alan, Mike F, Deb, Janis, Dan, Shayna, Dr Bill, Kimberly, and Bryan—your PDA National Team
Pitch In To Defrost The DCCC Freeze
Progressive Democrats of America (PDA) was founded in 2004 to support progressive candidates—including recruiting and electing primary challengers—because no other organization was dedicated to that mission. Our most famous achievement was "drafting" Bernie Sanders to run for President with our Run Bernie Run Campaign. Without that effort, it's possible that Bernie might never have run in 2016.
We launched our campaign in 2013—long before most people had even heard of Bernie. We all know how that turned out, with Bernie as a front runner for the 2020 nomination, elevating and mainstreaming the policies he ran on—Medicare For All, a Living Wage, Decisive Action on Climate, and much more. But it's not all good news. The Democratic Congressional Campaign Committee (DCCC or D Triple C) just announced a policy designed to freeze out challengers and to protect corporatist / GOP Lite incumbents.
As they put it: "The core mission of the DCCC is electing House Democrats, which includes supporting and protecting incumbents. To that end, the DCCC will not conduct business with, nor recommend to any of its targeted campaigns, any consultant that works with an opponent of a sitting Member of the House Democratic Caucus." (Emphasis added.)
The DCCC is trying to cut off the rise of new progressive stars—the next AOC—with these restrictive new rules. PDA is fighting back, and we need your help right now.
Please Pitch In To Help Us Thaw The DCCC Freeze
Join PDA Defying Establishment DCCC Democrats
Help Elect Progressive Congressional Challengers
A lot of people don't know that the DCCC withholds support from viable candidates unless they pay for polling and other services from DCCC-approved consultants. Now, the DCCC wants to shut down challengers before they can even get started by freezing out any consultant willing to help an up and coming candidate. This would make an already entrenched Congressional power structure impervious to needed challenges and even less accountable—the opposite of what voters demand and need.
PDA is fighting back! We need your help now to redouble our efforts to support challengers and to force the Democratic Party to be more democratic, progressive, and responsive to you. Please support our year-round work with a monthly gift of $50, $27, $20.20, $10, or $5—or a one-time gift—to rebuild, remake, and reimagine the Democratic Party as a true People's Party, dedicated to enacting the policies and legislation we all need to survive and thrive in the 21st century.
P.S. Join PDA's sustainers as we invest early to elect progressives in 2020


Stunning Diy Patio Table with Cooler for 33 Awesome Diy Summer Backyard Ideas that Will Blow Your. . A picture about diy patio table with cooler for the inspiration for patio decorating.
This is a post about stunning diy patio table with cooler for 33 awesome diy summer backyard ideas that will blow your, that is a part of decor ideas about Newest Design Ideas for Diy Patio Table with Cooler. You can browse another photos similar to this from the photos gallery below including: diy wooden pallet cooler design, diy patio table with built in beer wine coolers, 24 diy tutorials and tips, a diy table with built in drink coolers is the perfect way, diy patio table with built in beer wine coolers, pinterest diy crafts ideas, remodelaholic, how to build a patio cooler and grill cart bo, outdoor ice chest beverage cooler ideas for your patio or deck, wonderful diy patio table with built in wine cooler, etc. If you love and getting inspired by this ideas, then you can save it by right click on the picture and choose save image.
Just in case you charmed the above image about 33 Awesome DIY Summer Backyard Ideas That Will Blow Your, then do not forget to share or spread the picture on Facebook, Twitter, or Google .
More Pictures about "Stunning Diy Patio Table with Cooler for 33 Awesome Diy Summer Backyard Ideas that Will Blow Your"


Personality: As an Innocent Sweetheart, you're the youngest pilot, under-trained and inexperienced. But you make up for it with a heart of gold and an energetic spirit that just won't quit. Although most people don't have a lot of confidence in you, who can help but catch your infectious enthusiasm?
Advice: Believe in yourself more. You can do anything you set your mind to as long as you don't let your self-doubt get in the way. Your greatest asset is the trust that others hold in you, so never forget your friends and loved ones. At the same time, it might pay to be more realistic in your view of the world.
In other news, it turns out that Sunset Games is releasing a new RPG called "Moe-kei?! Gakuen: Aitsu wa Classmate!" I'm not sure how to properly translate the title, but it'd be something like "Moe-style (?!) Academy: That's my Classmate." According to the blurb on the website in the game your goal is to help out those who are troubled ("They'll surely say to you: "Thank you.") It's slated for some time in the summer, so I'm thinking I'll order it along with Mononoke Koyake (the Yuuyake Koyake sourcebook) after GenCon.
The other day I checked out some books from the library on educational role-playing. I'm currently reading The Effective Use of Role-Play by Morry van Ments, which is a nice overview of role-playing as an educational tool. I'll be putting together a full post about it when I'm done reading, but the differences in goals and the emphasis on "debriefing" after the actual role-play is finished are striking. It's helped me think a bit about the kind of atmosphere and approach I want for Raspberry Heaven, while Filip Luszczyk, Ben Lehman, and Fred Garber have all offered me very solid advice via the Forge.
With ordering Bliss Stage I prefer to wait till I see some reviews, previews, quickstarts or whatever. It had drawn my attention only a few months ago – too late to actually get a closer look at it during the development stage, so I'm not sure if I can find anything interesting for me in the game, other than the genre. I made quite a lot of RPG purchases lately anyway.


Pregnant Chrissy Teigen shows off baby bump in chic jumper dress and thigh-high boots as she joins husband John Legend and daughter Luna for family day out in NYC!
She confirmed she was expecting their second child a few months back,And Chrissy Teigen displayed her blossoming bump for all to see as she stepped out for a family day out in NYC with husband John Legend and daughter Luna.
The soon to be mum of 2 chose a stylish oversized jumper and thigh-high boots for the day as she headed to the Big Apple Circus in Manhattan with her family..


text:
PRACE Research Infrastructure calls for One Year Project Grants on three Tier-0 Computers and pilots a synchronized Pilot Call for Tier-1 Grants
PRACE, the Partnership for Advanced Computing in Europe, is a Research Infrastructure that enables researchers from across Europe to apply for time on the PRACE resources via a peer review process. This call marks the third regular call for the PRACE resources with the standard allocation time of one year, and includes a synchronized pilot call for the utilization of European Tier-1 resources. As the third Tier-0 system, the new supercomputer "HERMIT" is available for European researchers in this call for the first time.
PRACE is a Research Infrastructure that allows researchers from across Europe to apply for time on high-performance computers from a series of hosting nations via a central peer review process. This call is the third PRACE RI Regular call for Project access, inviting applications for high-end (Tier-0) computing resources to carry out projects which have high scientific quality and impact. Allocation will be for one year starting from 1st November 2011.
The call includes a Pilot Call for project access to Tier-1 resources, via DECI, the Distributed European Computing Initiative, providing single project cross-national access to national (Tier-1) HPC-resources. The DECI pilot call is synchronized in preparation for future integrated calls for Tier-0 and Tier-1 resources.
A short description of the available Tier-0 systems is:
IBM Blue Gene/P – JUGENE – hosted by GCS in Jülich, Germany. Details and terms of usage can be found at http://www.fz-juelich.de/jsc/jugene.
JUGENE has a peak performance of 1 Petaflop. It is composed of 294,912 processing cores with 4 cores forming a node with 2 GB of memory for a total of 147 TB.
The total available capacity for JUGENE in this call is 360 million compute core hours. The allocation period for JUGENE ends on August 31st, 2012.
Bull Bullx cluster – CURIE – funded by GENCI and installed at CEA, Bruyères-Le-Châtel, France. Details and terms of usage can be found at http://www-hpc.cea.fr/en/complexe/tgcc-curie.htm.
CURIE is composed by 2 different partitions:
A fat node partition open to PRACE calls since January 2011 and composed by 360 nodes with 32 cores per nodes, for a peak performance of 105 TFlops
A thin node partition, open to PRACE calls in Q1 2012 and composed by 5040 blades with 16 cores per node, for a peak performance of up to 1.5 PFlops
The total available capacity in this call for CURIE is:
On the thin nodes partition: 125 million compute core hours, with an 8 months allocation starting from March, 1st of 2012.
On the fat nodes partition: 31 million compute core hours, with a one year allocation starting from November, 1st of 2011.
Cray XE6 – HERMIT – hosted by GCS in HLRS, Stuttgart, Germany. Details and terms of usage can be found at http://www.hlrs.de/systems/platforms/cray-xe6-hermit/.
HERMIT has a peak performance of 1 Petaflop and is designed for sustained application performance and highly scalable applications. It is composed of 3552 dual socket nodes equipped with AMD Interlagos Processors leading to overall 113664 processing cores. Nodes are equipped with 32GB or 64GB main memory.
The total available capacity in this call for HERMIT is 160 million compute core hours.
The deadline for submission of proposals isJune 22nd, 2011at 16.00 CEST. All proposals must be submitted via the PRACE website at:
http://www.prace-ri.eu/hpc-access
The third PRACE Regular call is intended for large-scale projects of high scientific quality and for which a significant impact at European and international level is anticipated. High scalability of the code (at least 8000 compute coresfor JUGENE; for CURIE above 2048/1024 cores or above 512 cores with 64 GB of memory used per node or 256 cores with 16 threads allocated per task and 2048 cores for HERMIT) must be demonstrated. Proposals for project access must be ready to run. The projects must demonstrate scientific excellence and should cover topics of major relevance for European research. They should also include elements of novelty, transformative aspects, have a recognised scientific impact and include a dissemination plan. Possible practical and timely applications resulting from the project are also desirable. The projects should also demonstrate the possibility of achieving results which will be publishable in journals of recognised scientific impact.
All proposals will undergo PRACE technical and scientific assessment. The assessment procedure will adhere to the PRACE principles of peer review. For this call only proposals from academia are eligible and the project leader must be homed in a European Union country or a PRACERI country. Both systems also havefurther restrictions due to export and vendors rules. All applicants should expect to be notified of the outcome by the end of October 2011.
DECI provides single project cross-national access to European Tier-1 resources, provided up to now by DEISA project. Access will be awarded for a period of 12 months, beginning 1 November 2011.
Tier-1 resources are available on the following architectures:
Cray (XT and XE), IBM Blue Gene/P, IBM Power 6, Intel and PowerPC Clusters (various processor and memory configurations) and hybrid systems (clusters with GPGPU accelerators).
Four classes have been defined below.
Cray XT4/5/6 and Cray XE6 – three large Cray XE and XT systems are available at EPCC (UK), KTH (Sweden) and CSC (Finland). The largest of these machines has a peal performance of 360 T/flops and a total of 44,544 cores.
IBM Blue Gene/P – three BG/P systems are available at IDRIS (France), RZG (Germany) and NCSA (Bulgaria). The largest of these machines has a peak performance of 139 T/flops and a total of 40,960 cores.
IBM Power 6 – three IBM Power 6 systems are available at RZG (Germany), SARA (The Netherlands) and CINECA (Italy). The largest of these machines has a peak performance of 98 T/flops.
Clusters – PRACE offers access to eight clusters at FZJ (Germany, Bull Nehalem cluster), LRZ (Germany, Xeon cluster), HLRS (Germany, NEC Nehalem cluster plus GP/GPU cluster), CINES (France, SGI EX820), BSC (Spain, IBM PowerPC), CINECA (Italy, Westmere plus GP/GPU cluster), PSNC (Poland, Bullx plus GP/GPU cluster and HP cluster) and ICHEC (Ireland, SGI EX820). The largest cluster has a peak performance of 183 T/flops and a total of 17,664 cores.
In total the number hours on the Tier-1 resources is more than 54 million core hours.
DECI enables European researchers to obtain access to the most powerful national (Tier-1) computing resources in Europe, regardless of their country of origin or work and to enhance the impact of European science and technology at the highest level.
Proposals must deal with complex, demanding, innovative simulations that would not be possible without Tier-1 access.
A continuous call for applications for PRACE preparatory access is now open.
More information and application form: http://www.prace-ri.eu/hpc-access, see also a related document at http://www.prace-ri.eu/IMG/pdf/PRACE_third_regular_call.pdf
More information: peer-review@prace-ri.eu
About PRACE: The Partnership for Advanced Computing in Europe (PRACE) is an international non-profit association with its seat in Brussels. The PRACE Research Infrastructure (RI) provides a persistent world-class High Performance Computing (HPC) service for scientists and researchers from academia and industry. The PRACE leadership systems form the apex of the performance pyramid and are well integrated into the European HPC ecosystem. The preparation and implementation of the PRACE RI receive EC funding under grants RI-211528 and FP7-261557.
More information about JUGENE, CURIE and HERMIT:
http://www.fz-juelich.de/jsc/jugene
http://www-hpc.cea.fr/en/complexe/tgcc-curie.htm
http://www.hlrs.de/systems/platforms/cray-xe6-hermit/


Suppose that you are a military planner advising the commander in a (just) war with Niatirb.
1. Suppose that you are a military planner advising the commander in a (just) war with Niatirb. You are also a Kantian or Thomist (your pick) who regards intentionally killing the innocent as always wrong. What guidance would you provide, and why, in the following situation: One of our vital objectives is to take out a nuclear reactor in the countryside of Niatirb. The reactor itself is a legitimate military target of significant strategic value, but the Niatirbian dictator has surrounded the plant with 100 involuntary "human shields." The plant cannot be destroyed without killing them. Hint: You will want to consider the principles of discrimination, proportionality, and double effect. Also, if it is helpful, you may stipulate additional details, provided they are plausible and do not fundamentally change the situation (you may not, e.g., stipulate that you just invented a bomb that destroys only inorganic materials).
Q: Criminal Justice 250 Please post a 150-300-word response to the following discussion question by clicking on Reply.
Q: which of the following is not one of the general strategic types?
Q: at 60 the vapor pressure of pure water is 149.44 mmhg and that above an aqueous sucrose solution is 119.55 mmhg.


text:
The Youngest Profession est un film dramatique américain réalisé par Edward Buzzell et sorti en 1943.

Synopsis

Fiche technique
 Titre original : The Youngest Profession
 Réalisation : Edward Buzzell
 Scénario : Charles Lederer et Leonard Spigelgass
 Direction artistique :
 Décors :
 Costumes :
 Photographie :
 Montage : Ralph E. Winters
 Musique : David Snell
 Production : B.F. Zeidman
 Société de production : MGM
 Société de distribution : MGM
 Format : Noir et blanc - 35 mm - 1,37:1 - Son mono
 Pays : États-Unis
 Langue : anglais
 Durée :
 Genre : drame
 Date de sortie :  : 1943

Distribution
 Virginia Weidler
 Edward Arnold : Burton V. Lyons
 John Carroll
 Agnes Moorehead : Miss Featherstone
 Jean Porter : Patricia Draw
 Ann Ayars : Susan Thayer
 Marta Linden : Edith Lyons
 Ray Teal : le chauffeur de taxi
 Claire McDowell : une femme
 Aileen Pringle
 Marjorie Gateson
 Dorothy Morris : une secrétaire

Notes et références

Liens externes

Film américain sorti en 1943
Film dramatique américain
Film américain en noir et blanc
Film de Metro-Goldwyn-Mayer
Film tourné aux Metro-Goldwyn-Mayer Studios
Film tourné en Californie
Film réalisé par Edward Buzzell

redpajama_set_name: RedPajamaWikipedia


text:
Review of WIC Food Packages: An Evaluation of White Potatoes in the Cash Value Voucher: Letter Report (2015)
Chapter: Summary
« Previous: Front Matter
Page 1 Share Cite
Suggested Citation:"Summary." Institute of Medicine. 2015. Review of WIC Food Packages: An Evaluation of White Potatoes in the Cash Value Voucher: Letter Report. Washington, DC: The National Academies Press. doi: 10.17226/20221.
The Dietary Guidelines for Americans (DGA) are the cornerstone of federal nutrition guidance. The policy document, revised every 5 years, underpins the dietary goals of federal nutrition assistance programs, including the Special Supplemental Nutrition Program for Women, Infants, and Children (WIC). Given that the previous Institute of Medicine (IOM) review of WIC food packages applied the 2005 DGA as a benchmark, and that the 2010 DGA are currently undergoing reevaluation and update, the U.S. Department of Agriculture (USDA) requested that the IOM undertake a review of the WIC food packages to bring the program into alignment with current dietary guidance. This letter report is the first in a series of reports by the IOM Committee to Review WIC Food Packages in response to that request. For this report, the committee was tasked with assessing the impact of the 2009 regulation to allow the purchase of vegetables and fruits, excluding white potatoes, with a cash value voucher (CVV) on food and nutrient intakes of the WIC population and to consider whether white potatoes should be permitted for purchase with the voucher. The recommendations were to consider the effects on diet quality, the health and cultural needs of the WIC population, and allow for effective and efficient administration nationwide in a cost-effective manner. Following this report, phases I and II of the Review of WIC Food Packages study will update the findings presented here, evaluate the current WIC food packages as outlined in the statement of task, and recommend updates, in the context of the 2015 DGA.
Although the available data did not permit a direct comparison between
food and nutrient intakes before and after CVV implementation, data from the National Health and Nutrition Examination Survey (NHANES) (2007–2010) indicated that intakes of starchy vegetables (which includes white potatoes) among WIC participants are 64 and 56 percent of the 2010 DGA goals for children and women, respectively. For children, intakes of several nutrients of concern (vitamin D, calcium, potassium, and fiber) fall short of current Dietary Reference Intakes (DRIs). Women's intakes of all nutrients of concern (vitamin C for iron absorption, folate, vitamin D, calcium, potassium, iron, and fiber) are in need of substantial improvement. Although there is some evidence that attention to glycemic index (GI) is important for individuals with type 2 diabetes or gestational diabetes, the GI value of white potatoes depends on the method of preparation. Other evidence indicates that consumption of vegetables and fruits may have long-term health benefits. The committee assessed the effect of various cost-neutral shifts in the intake of categories of vegetables and fruits to accommodate higher consumption of potentially WIC-eligible white potatoes, applying ad hoc assumptions. The scenarios tested included doubling at-home intake of white potatoes or doubling total intake of white potatoes. For children, this resulted in a 2 to 5 percent increase in potassium intake with intakes of other nutrients of concern changing from 0 to 3.3 percent. For women, potassium intakes increased from 2.7 to 6.7 percent and intakes of other nutrients of concern changed from 0 to 4.6 percent. Energy intake increased by less than 2 percent across all scenarios. Apart from the subscore for total vegetable intake (which increases by default), individual subscores of the Healthy Eating Index (a measure of diet quality) change by no more than 5 percent for either women or children under the tested scenarios. The projected changes are small across scenarios because the CVV covers approximately 5 percent of monthly food costs for women 19–50 years of age-based 2014 Thrifty Food Plan estimates. Information related to participant satisfaction and use of the CVV including the influence of culture, as well as on vendor response to CVV implementation, was limited. The committee makes the following recommendations (see the Recommendations section of the report for supporting rationale):
The committee recommends that the U.S. Department of Agriculture allow white potatoes as a WIC-eligible vegetable, in forms currently permitted for other vegetables, in the cash value voucher pending changes to starchy vegetable intake recommendations in the 2015 Dietary Guidelines for Americans (DGA). If there are relevant changes in the 2015 DGA, the committee should reevaluate this recommendation.
The committee recommends that the U.S. Department of Agriculture and the U.S. Department of Health and Human Services collaborate to achieve expansion of data collection on dietary intakes for pregnant, breastfeeding, and postpartum women in the National Health and Nutrition Examination Survey.
The committee recommends that the U.S. Department of Agriculture undertake a separate, comprehensive examination of currently available data to assess the effectiveness of the current cash value voucher in meeting participants' food pattern and dietary intake goals as recommended by the Dietary Guidelines for Americans, including use of white potatoes in the context of cultural diversity among WIC participants.
The committee recommends that the U.S. Department of Agriculture allocate resources to support studies related to (1) participant satisfaction with the cash value voucher (CVV); (2) the strategies participants use to decide how much of the CVV to spend; (3) the strategies participants use to decide how to apportion this benefit among the vegetables and fruits, between vegetables and fruits, and between the CVV and other food purchases; (4) how vendors have changed the WIC-eligible vegetables and fruits they stock because of the implementation of the CVV; and (5) how the CVV and its implementation have affected vendors.
Next: Letter Report »
Review of WIC Food Packages: An Evaluation of White Potatoes in the Cash Value Voucher: Letter Report Get This Book
Review of WIC Food Packages: An Evaluation of White Potatoes in the Cash Value Voucher assesses the impact of 2009 regulation to allow the purchase of vegetables and fruits, excluding white potatoes, with a cash value voucher on food and nutrient intakes of the Special Supplemental Nutrition Program for Women, Infants, and Children (WIC) population and to consider whether white potatoes should be permitted for purchase with the voucher. This report considers the effects on diet quality, the health and cultural needs of the WIC population, and allows for effective and efficient administration nationwide in a cost-effective manner. Review of WIC Food Packages: An Evaluation of White Potatoes in the Cash Value Voucher recommends that the U.S. Department of Agriculture should allow white potatoes as a WIC-eligible vegetable, in forms currently permitted for other vegetables, in the cash value voucher pending changes to starchy vegetable intake recommendations in the 2015 Dietary Guidelines for Americans.
Front Matter i–x
Letter Report 5–38
Appendix A: Acronyms and Abbreviations 39–40
Appendix B: Statement of Task 41–42
Appendix C: Workshop Agendas 43–46
Appendix D: Literature Search Strategy 47–50
Appendix E: Dietary Reference Intakes 51–54
Appendix F: Description of Sensitivity Analysis Scenarios 55–56
Appendix G: Food Group and Subgroup Intakes 57–62
Appendix H: Nutrient Intakes 63–70
Appendix I: Nutrient Profiles 71–74
Appendix J: Food Group Distributions 75–82
Appendix K: Healthy Eating Index 2010 Assessment 83–86
Appendix L: Background Example Data for Sensitivity Analysis 87–98
Appendix M: Committee Biosketches 99–106


text:
var exec = require('cordova/exec');
function AppAvailability() {}
AppAvailability.prototype.check = function(str, callback) {
    exec(
        function(result) {
            callback(result);
        },
        function(error) {
            callback(error);
        },
        "AppAvailability",
        "checkAvailability",
        [str]
    );
}

module.exports = new AppAvailability();


Spoken Soul Festival is celebrating an equally simple and complicated concept: the word. SSF 12's theme, #WordIsBond, explores how in the digital age words have no boundaries and comments on how because of this, words are more powerful than ever before in our history. The open admission showcase will experience the rich cultural diaspora that they have come to expect from the SSF's signature event: women dancers, poets, visual artists, vocalists, and a female DJ, all representing different cultures and unique voices. This year's theme, #WordIsBond, will take center stage, weaving in, out and in between dancers' limbs, peeking out from visual works, and swirling through the air in sync with live musical notes.


Irene Loves Elephants: May 9th What Is This?
Well may you ask! It actually is a humble Shower Cap. And you may also well ask, Irene why are you posting a photo of a shower cap?
The reason I am posting a photo of a shower cap, is that I have an abundance here at home of shower caps. Mainly due to the number of hotels I stay at, whether it is for work or pleasure. Other guests may take the moisturisers, the tea, the coffee, the soaps, but not me. I take the shower caps (and just between you and me, I make sure I put them in my suitcase every day so they are replaced on a daily basis - but I am telling you that in confidence)..
Usually shower caps are used for a very different purpose in this household. They make the most perfect food covers when storing left overs in your refrigerator.


Call NOW for more information on Mexican Thatch.
Mexican Rain Cape Thatch Features: Versatile product; can be cut using scissors to any shape between the knots without unraveling. Kind a like cutting a fish net.
Applications for Mexican Rain Cape Thatch: Apply to a plywood deck with staples or on horizontal 1/2" x 1/2" batten boards to create a more authentic looking thatched roof.
Specifications of Mexican Rain Cape Thatch: Hand-woven palm leaf sheet is for 30" x 6' x 1" thick and weigh 8 lbs each roll.
Sold individually in one long thatch roll. Can measure up to 8' long.
Mexican Rain Cape Thatch Dimensions: 30" x 6' x 1" thick. Each roll provides 12-17 sq ft of coverage. Please allow material for overhang also when calculating thatched material.
Our Mexican Rain Cape thatching will last 5-6 years in dryer climates outside and indefinitely inside.
Add 2 years to your thatch life by purchasing our Thatch SealerTM for $52.99 a gallon with free shipping and it will cover one thatch roll on both sides.


text:
Home / Where is Leelee Sobieski and her Designer Husband Adam Kimmel?
Where is Leelee Sobieski and her Designer Husband Adam Kimmel?
Published Date 08th Feb. 2018, 12:29 pm Binesh Shrestha
Image Source: The News
Leelee Sobieski's Husband Adam Kimmel
Leelee and Kimmel Welcomed First Child before Marriage
Leelee's hint to leave Hollywood in 2012
Second Child; Son Martin
Leelee Sobieski's husband Adam Kimmel along with their two children and wife lives in the 4,800-square-foot Tribeca Loft in New York. Designer Kimmel with his family moved into the loft in 2007.
The beautiful loft comprises Ken Price sculptures, artworks of Raymond Pettibon, George Condo, Theodor Seuss Geisel and 1970's seminal figures.
Meanwhile, Leelee Sobieski is fully dedicated to being a mom with two children and has eased off her acting projects for a while. Her Husband, Kimmel too is taking a hiatus from his long eight-year-old menswear collection. The couple is busy being parents. Let's have an in-depth look at their life and parenthood.
Leelee Sobieski's husband Adam Kimmel in 2012 marked his greatness in the fashion world.
His label started in 2005 and was growing steadily. Designer Kimmel had collaborated with Supreme and Carhartt and together were making astounding sales in the high fashion world.
Kimmel's idea was groundbreaking and much different from the conventional presentations. He used to creatively stage and ambitiously present his work resulting in a trademark of his own. According to critic Tim Blanks Kimmel's 2012 winter collection of the set including models wearing fighter pilots masks was his greatest idea.
Naturally, Kimmel seemed to reach his peak, just when he canceled his Spring 2013 collection and simply walked away from the business. The empire Kimmel had built after seemingly seven years of hard work was abandoned by him. Kimmel reported to GQ style:
"The company was growing. Infact, very fast. The last two years the company was doubling in revenue each year. So then I felt, I could become a slave to this thing."
Though Leelee Sobieski's husband Kimmel said he would be taking a one-year hiatus, he didn't return. All the years Kimmel had disappeared, he could still be heard in the fashion world.
It seems absurd looking at his commercial success and an endless tank of creativity and then he just walks away. Kimmel remained at the top of his game for almost 20 years. As Kimmel stated:
"I was just like, 'I want to be a good husband, a good dad. I want to take a year off, I want to work on that, and if this is the thing that's meant to be, great, I'll return."
Kimmel spent his free time in his New York studio making clothes with different ideas. Things changed in his life when he met his soul mate Leelee Sobieski in New York possibly in 2009. As Leelee got divorced from her brief marriage with Matt Devis in 2009.
Certainly, at the first glance, Adam seemed out of her league. But, Kimmel and Sobieski soon began spending time together and became really close.
The lovely pair was blessed with a daughter Louisanna Ray Kimmel on December 15, 2009, in New York.
Leelee Sobieski's daughter Louisanna Ray Kimmel. Sobieski and husband Kimmel welcomed their daughter on December 15, 2009.
Image Source: People
Then they married in August 2010. We can guess that Leelee and Kimmel tied their knots on August 31, 2010, as Leelee shared an Instagram post on August 31, 2017, and tweeted,
7 years married to this guy! ❤?? @ Hotel Raphael Paris https://t.co/RDy8oBNcd8
— leelee (@iamleelee) September 1, 2017
Adam then decided to take a break from his professional career. He just wanted to be Leelee Sobieski's husband and a dad for a while.
Leelee's brief marriage in 2008 to Matt Davis is forgotten after her divorce in 2009 and only Adam Kimmel is recognized as her only love.
Back in 2012, Leelee had hinted that she was ready to leave Hollywood due to ninety percent of the acting job including the sexual stuff. According to US Magazine, Leelee explained:
"It's such a strange fire to play with. Our relationship is surely strong enough to handle it, but if you're going to walk through fire, there has to be something incredible on the other side."
Leelee was a virgin until age 26, to your surprise the actress herself had stated :
I think age 26 is old to lose your virginity, but it was important to me. I wanted to remain a virgin until after I was married. I didn't have any religious regions or anything like that but simply because, to me, my virginity was the most precious gift that I could ever give to a man. And, I wanted to be sure I was giving it to the right man.
Leelee is not just an actress but a writer and painter as well.
After four years of marriage, in 2014, the couple welcomed their second child, a son Martin Kimmel.
Leelee Sobieski and Adam Kimmel with son Martin at beach in St. Barts on January 2016.
Image Source: Daily Mail
Nobody realized that Leelee was pregnant as she kept it secret for four months according to Hollywood Life.
The conclusion is undoubted that both of them kept their professional career aside to focus more on their family and kids. Both of them despite being talented and creative in their careers had the only desire to give a proper parenthood to their infants.
The beautiful duo along with their family currently are living a happy life in New York.
For more updates, stay with SuperbHub.
Adam KimmelGeorge CondoLeelee SobieskiLouisanna Ray KimmelMartin KimmelMatt DavisRaymond PettibonTheodor Seuss Geisel
4 Useful Tips to Help Your Spouse Cope with Addiction
First Timers Guide to Hair Extensions
5 Small Ways to Treat Yourself Better
These 4 Signs Mean Your Spouse Could Be Looking for Love Elsewhere
Tamra Judge Leaves Real Housewives of Orange County


text:
Judaic Values
The Record - Campus Newsletter
Communication Procedures
TUC Life
Digital Viewbook
CEO and Senior Provost
Provost and CAO
Touro College & University System
Touro Western Division
TCUS Directory
Bursar Office
Calendar (Campus)
Calendar (Master)
Online Book Store
TouroOne Portal
Medical Health Science-COM
Support TUC
Quick Links Request Information MOBEC Calendar (Campus) Calendar(Master) Campus Map Canvas CARE Team Catalog Clinical Skills Laboratory Dining & Catering Email (Faculty/Staff) Email (Students) Facilities Faculty Senate Faculty/Staff Directory Human Resources Information Technology .Learn Library Online Bookstore Touro University Gear Office of Sponsored Programs TouroOne Portal VPN
Search TU Site Search
Dual & Joint Degrees
DO/MPH
PH Program Home
MPH Degrees & Programs
Prospective Students/ Request Info
Career Mart/Jobs
DO/MPH students taking a break from class
DO/MPH DUAL DEGREE PROGRAM
The discipline of osteopathic medicine –with its traditional emphasis on treating the whole person, education, and prevention –is particularly well‐suited to complement public health in its mission to promote and protect individual and population health. Students concurrently enrolled in the DO/MPH Program are provided with an integrated curriculum that focuses on understanding that with each patient, there is an opportunity to impact overall community health by examining health issues on a population basis rather than the individual. Students gain an awareness of population medicine -beyond the emphasis on just how to treat individual patients- as well as healthcare systems and how they work. The Doctor of Osteopathic Medicine (DO)/MPH Dual Degree at TUC provides students:
Increased knowledge of and sensitivity to the political, historical, economic and social environments of health promotion and health services delivery;
Increased capacity to incorporate preventive practices into care of individual patients;
Greater knowledge in the area of health policy and management;
Opportunities for physicians who want to initiate change in managed health care, hospitals, and acute care centers;
Planning, implementation, and evaluation of interventions to improve the health of a population; and
Ability to investigate outbreaks of disease or symptoms in a population.
Physicians with MPH degrees enjoy a wide range of career choices that can benefit the overall care they can offer their patients and their community:
Leadership positions with health departments, federal and international agencies, managed care organizations and healthcare providers, schools of medicine and public health;
Performing clinical research;
Planning and implementing disease prevention and control strategies; and
Consulting in global health research and programs.
Why get your dual degree at TUC?
There are many advantages to getting your MPH degree while concurrently obtaining your DO degree in the College of Osteopathic Medicine (COM):
The TUC Public Health Program is dedicated to reducing health disparities in local and global communities with an unwavering focus on social justice.
While the full MPH degree is 42 units of study, as a dual degree student you complete 30 units within the Public Health Program, and the remaining 12 units are transferred from the DO curriculum and cover related cross‐over content.
The TUC Public Health Program is accredited by the Council on Education for Public Health (CEPH), an indicator of a public health program's quality and viability. Certain professional positions and fellowships are only open to those with degrees from CEPH‐accredited programs.
DO/MPH Curriculum
A total number of 30 units are required for the DO/MPH Dual Degree. Fifteen units are in the 5 core public health disciplines: Biostatistics, Epidemiology, Environmental Health Science, Health Policy and Management, and Social and Behavioral Sciences. Students complete 10 units in their specialty track, Community Health or Global Health, and 4 units of the Public Health Field Study. Students have the option to enroll in the 1-unit MPH Capstone Course, OR the 1-unit Certified in Public Health (CPH) Prep Exam Course, which prepares students to sit for the National Board of Public Health Examiners CPH Exam.
The COMMUNITY ACTION FOR HEALTH CONCENTRATION prepares students to respond to the health needs of communities, especially those communities that face unique vulnerabilities due to current and historical policies and practices and is comprised of the following courses:
Health Disparities and Community Organizing
Health Education and Promotion
The GLOBAL HEALTH CONCENTRATION prepares students to be global health advocates and leaders. Our curriculum reflects the realities of health around the world and reinforces the links between countries at different stages of economic development. The Global Health Concentration is comprised of the following courses:
Essentials of Global Health
Emerging Health Threats
The HEALTH EQUITY & CRIMINAL JUSTICE CONCENTRATION is a new emphasis in the Public Health Program designed to address the impact of criminal justice involvement and incarceration on the health of individuals, families and communities. Students gain an understanding of the needs of these populations through field study and specialized courses including:
Criminal Justice and Public Health
Criminal Justice Law and Advocacy
MPH CULMINATING EXPERIENCE: Upon completion of all MPH core and track-required courses, students must complete the following courses:
CPH Prep Exam Course (1 Unit): This course prepares students for the 4-hour CPH Exam, which consists of 200 multiple choice questions and covers the five core areas of knowledge offered in CEPH–accredited schools and programs, as well as cross–cutting areas relevant to contemporary public health.
MPH Capstone Course (1 Unit): Students who elect to complete a Capstone Project in lieu of the CPH Exam are required to produce a substantial, original, independently written manuscript concerning a significant public health problem and share and defend their work during an oral presentation.
Public Health Field Study: In either Y3 or Y4, all DO/MPH students are required to complete a 4-unit Public Health Field Study over a 6-week block under the guidance of preceptors at affiliated public health field study organizations that serve as field study placement sites. The Field Study also satisfies the COM Research Rotation Elective. Please see track-specific requirements below:
Community Health Concentration students complete the Field Study at Community Health field study sites that include, but are not limited to: county health departments, state and federal health agencies, community health organizations, hospitals, clinics, managed care organizations, academic institutions, California correctional facilities, philanthropic and voluntary health agencies, and non-profit organizations.
Global Health Concentration students conduct their field studies at sites in Bolivia, Cambodia, Ethiopia, Nepal, and Uganda under the guidance of site preceptors and course coordinators at public health institutions, universities, ministries of health, non-governmental organizations, and United Nations agencies.
Options for Dual Degree Study
The Program's academic calendar is divided into semesters - from August to December (Fall), January to May (Spring) - and into a session from June to August (Summer). Students may pursue the dual DO/MPH degree in one of two ways:
Begin public health courses the summer before entering COM. The didactic coursework will be completed during that first summer and the summer after the first year of COM. Students may then take the CPH exam and complete the Public Health Field Study during 6-week blocks designated for public health rotations; OR
Add a 5th year to the four years in COM. Students take a leave of absence from COM after completing their second year and boards, and spend a year immersed in public health. All didactic coursework is completed during the year, and the Field Study is completed during 6-week blocks designated for public health rotations.
There are two benefits to the 5th year option: 1) If you are interested in completing a Capstone Project rather than taking the CPH exam, this gives you the time to work closely with a faculty member; and 2) If you are unable to start the MPH program the summer before starting COM, you can still take advantage of the streamlined nature of the DO/MPH Dual Degree Program which requires only 30 units.
For specific information or questions regarding the DO/MPH Program, contact:
Gayle Cummings, PsyD, MPH
Assistant Dean and Program Director
email:gayle.cummings@tu.edu
Our Judaic Values Touro College Touro Western Division Touro Nevada Campus Safety Privacy Policy Contact Us Master Calendar Title IX
Copyright 2005 - 2020, Touro University, All Rights Reserved.


text:
Comic-Con 2016: The Museums That a Broken "Star Trek" Bridge Built
Jana Monji July 28, 2016
Dumpster divers aside, the average person would be surprised at what ends up in the trash. In August 2012, a "Star Trek" fan found a Paramount-built, Star Trek Enterprise-D display bridge in the dumpster. (An Enterprise-D style of bridge is the one used in the TV series "Star Trek: The Next Generation.") In a moment of complete idealistic insanity, Huston Huddleston decided he wanted to preserve it. He set off on what would turn out to be a five-year mission that began with a crowd-funded restoration and looks to culminate in the founding of two museums: The Hollywood Sci-Fi Museum and the Hollywood Horror Museum.
His family isn't without Hollywood connections. Huddleston's father, Floyd Huddleston (1918-1991) wrote songs for films such as "The Ballad of Josie," "Midnight Cowboy" and Disney's "The Aristocats" ("Ev'rybody Wants to Be a Cat"). For Disney's animated feature "Robin Hood," Floyd Huddleston and George Bruns' song, "Love," sung by Huddleston's wife Nancy Adams, was nominated for an Academy Award.
Huston is proud of the late Floyd, but undoubtedly, his father would be and his mother is proud of him. Huddleston has not only restored the bridge, but reached far beyond that original goal. What good is a crowd-funded restored "Star Trek" bridge if one can't share it? How does one share something with hundreds of sponsors? The idea of a museum took hold. But is there really a need for a "Star Trek" only museum? And what would the museum's goal be?
True to the old values of "Star Trek," the goal has become one of sharing the wealth and educating generations: An educational museum not just for "Star Trek" treasures, but science fiction props from yesteryear and even more recent films.
Huddleston now has more than just a "Star Trek" bridge or a "Star Trek" captain's chair. Last year at San Diego Comic-Con, Conan O'Brien's people reached out to Huddleston, who had brought a "Dr. Who" TARDIS. O'Brien was in his first year at San Diego Comic-Con and the current/12th Dr. Who, Peter Capaldi, was one of his guests. Of course, what could be better than Capaldi coming out of the TARDIS?
At other conventions, a "Star Trek" captain's chair or a life-sized model of Iron Man will turn up. For San Diego Comic-Con 2016, the museum had a modest booth with the screen-used Borg Alcove from "Star Trek: First Contact" and "Star Trek: Voyager" (used by actors Patrick Stewart and Jeri Ryan).
Huddleston was one of 3,000 fans at the red carpet premiere of "Star Trek Beyond" on Wednesday night of SDCC. He came away pleased and ranked the "Star Trek" movies as follows:
1. "Star Trek II: Wrath of Khan" (1982)
2. "Star Trek VI: Undiscovered Country" (1991)
3. "Star Trek III: The Search for Spock" (1984)
4. "Star Trek: First Contact" (1996)
5. "Star Trek: The Motion Picture," director's cut (1979)
6. "Star Trek Beyond" (2016)
7. "Star Trek" (2009)
8. "Star Trek IV: The Voyage Home" (1986)
9. "Star Trek V: The Final Frontier" (1989)
10. "Star Trek Into Darkness" (2013)
11. "Star Trek: Insurrection" (1998)
12. "Star Trek Generations" (1994)
13. "Star Trek: Nemesis" (2002)
If you didn't get in to SDCC this year, the Borg Alcove will appear at other events, but Huddleston isn't sure which ones yet. He plans to have a booth at:
ScareLA: Season of the Witch (Los Angeles, CA, August 6 - 7)
Long Beach Comic-Con (Long Beach, CA, September 17 - 18)
Stan Lee's Comikaze Expo (Los Angeles, CA, October 28 - 30)
Walker Stalker Con (Atlanta, GA, October 28 - 30)
In 2017, two world tours are planned for exhibits of the Hollywood Sci-Fi Museum and the Hollywood Horror Museum. The brick-and-mortar versions of both museums are currently in the planning stages.
Although the museum won't be open in time for the 50th anniversary of "Star Trek," it will be doing giveaways and promotions through Paramount on its websites. For more information, visit the Hollywood Sci-Fi Museum website.
Jana Monji
Jana Monji, made in San Diego, California, lost in Japan several times, has written about theater and movies for the LA Weekly, LA Times, and currently, Examiner.com and the Pasadena Weekly. Her short fiction has been published in the Asian American Literary Review.
Film About A Father Who
Glenn Kenny