text:
#ifndef TENSORFLOW_PYTHON_LIB_CORE_CUSTOM_FLOAT_H_
#define TENSORFLOW_PYTHON_LIB_CORE_CUSTOM_FLOAT_H_

// Must be included first
// clang-format off
#include "tensorflow/tsl/python/lib/core/numpy.h" // NOLINT
// clang-format on

// Support utilities for adding custom floating-point dtypes to TensorFlow,
// such as bfloat16, and float8_*.

#include <array>   // NOLINT
#include <cmath>   // NOLINT
#include <limits>  // NOLINT
#include <locale>  // NOLINT
#include <memory>  // NOLINT

// Place `<locale>` before <Python.h> to avoid a build failure in macOS.
#include <Python.h>

#include "absl/strings/str_cat.h"
#include "third_party/eigen3/Eigen/Core"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/types.h"

#undef copysign  // TODO(ddunleavy): temporary fix for Windows bazel build
                 // Possible this has to do with numpy.h being included before
                 // system headers and in bfloat16.{cc,h}?

namespace tensorflow {
namespace custom_float_internal {

struct PyDecrefDeleter {
  void operator()(PyObject* p) const { Py_DECREF(p); }
};

// Safe container for an owned PyObject. On destruction, the reference count of
// the contained object will be decremented.
using Safe_PyObjectPtr = std::unique_ptr<PyObject, PyDecrefDeleter>;
inline Safe_PyObjectPtr make_safe(PyObject* object) {
  return Safe_PyObjectPtr(object);
}

inline bool PyLong_CheckNoOverflow(PyObject* object) {
  if (!PyLong_Check(object)) {
    return false;
  }
  int overflow = 0;
  PyLong_AsLongAndOverflow(object, &overflow);
  return (overflow == 0);
}

template <typename T, typename Enable = void>
struct TypeDescriptor {
  // typedef ... T;  // Representation type in memory for NumPy values of type
  // static int Dtype() { return NPY_...; }  // Numpy type number for T.
};

template <typename T>
struct CustomFloatTypeDescriptor {
  static int Dtype() { return npy_type; }

  // Registered numpy type ID. Global variable populated by the registration
  // code. Protected by the GIL.
  static int npy_type;

  static PyTypeObject type;
  // Pointer to the python type object we are using. This is either a pointer
  // to type, if we choose to register it, or to the python type
  // registered by another system into NumPy.
  static PyTypeObject* type_ptr;

  static PyNumberMethods number_methods;

  static PyArray_ArrFuncs arr_funcs;

  static PyArray_Descr npy_descr;
};
template <typename T>
int CustomFloatTypeDescriptor<T>::npy_type = NPY_NOTYPE;
template <typename T>
PyTypeObject* CustomFloatTypeDescriptor<T>::type_ptr = nullptr;

// Representation of a Python custom float object.
template <typename T>
struct PyCustomFloat {
  PyObject_HEAD;  // Python object header
  T value;
};

// Returns true if 'object' is a PyCustomFloat.
template <typename T>
bool PyCustomFloat_Check(PyObject* object) {
  return PyObject_IsInstance(
      object, reinterpret_cast<PyObject*>(&TypeDescriptor<T>::type));
}

// Extracts the value of a PyCustomFloat object.
template <typename T>
T PyCustomFloat_CustomFloat(PyObject* object) {
  return reinterpret_cast<PyCustomFloat<T>*>(object)->value;
}

// Constructs a PyCustomFloat object from PyCustomFloat<T>::T.
template <typename T>
Safe_PyObjectPtr PyCustomFloat_FromT(T x) {
  Safe_PyObjectPtr ref =
      make_safe(TypeDescriptor<T>::type.tp_alloc(&TypeDescriptor<T>::type, 0));
  PyCustomFloat<T>* p = reinterpret_cast<PyCustomFloat<T>*>(ref.get());
  if (p) {
    p->value = x;
  }
  return ref;
}

// Converts a Python object to a reduced float value. Returns true on success,
// returns false and reports a Python error on failure.
template <typename T>
bool CastToCustomFloat(PyObject* arg, T* output) {
  if (PyCustomFloat_Check<T>(arg)) {
    *output = PyCustomFloat_CustomFloat<T>(arg);
    return true;
  }
  if (PyFloat_Check(arg)) {
    double d = PyFloat_AsDouble(arg);
    if (PyErr_Occurred()) {
      return false;
    }
    // TODO(phawkins): check for overflow
    *output = T(d);
    return true;
  }
  if (PyLong_CheckNoOverflow(arg)) {
    long l = PyLong_AsLong(arg);  // NOLINT
    if (PyErr_Occurred()) {
      return false;
    }
    // TODO(phawkins): check for overflow
    *output = T(static_cast<float>(l));
    return true;
  }
  if (PyArray_IsScalar(arg, Half)) {
    Eigen::half f;
    PyArray_ScalarAsCtype(arg, &f);
    *output = T(f);
    return true;
  }
  if (PyArray_IsScalar(arg, Float)) {
    float f;
    PyArray_ScalarAsCtype(arg, &f);
    *output = T(f);
    return true;
  }
  if (PyArray_IsScalar(arg, Double)) {
    double f;
    PyArray_ScalarAsCtype(arg, &f);
    *output = T(f);
    return true;
  }
  if (PyArray_IsScalar(arg, LongDouble)) {
    long double f;
    PyArray_ScalarAsCtype(arg, &f);
    *output = T(f);
    return true;
  }
  if (PyArray_IsZeroDim(arg)) {
    Safe_PyObjectPtr ref;
    PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(arg);
    if (PyArray_TYPE(arr) != TypeDescriptor<T>::Dtype()) {
      ref = make_safe(PyArray_Cast(arr, TypeDescriptor<T>::Dtype()));
      if (PyErr_Occurred()) {
        return false;
      }
      arg = ref.get();
      arr = reinterpret_cast<PyArrayObject*>(arg);
    }
    *output = *reinterpret_cast<T*>(PyArray_DATA(arr));
    return true;
  }
  return false;
}

template <typename T>
bool SafeCastToCustomFloat(PyObject* arg, T* output) {
  if (PyCustomFloat_Check<T>(arg)) {
    *output = PyCustomFloat_CustomFloat<T>(arg);
    return true;
  }
  return false;
}

// Converts a PyReduceFloat into a PyFloat.
template <typename T>
PyObject* PyCustomFloat_Float(PyObject* self) {
  T x = PyCustomFloat_CustomFloat<T>(self);
  return PyFloat_FromDouble(static_cast<double>(static_cast<float>(x)));
}

// Converts a PyReduceFloat into a PyInt.
template <typename T>
PyObject* PyCustomFloat_Int(PyObject* self) {
  T x = PyCustomFloat_CustomFloat<T>(self);
  long y = static_cast<long>(static_cast<float>(x));  // NOLINT
  return PyLong_FromLong(y);
}

// Negates a PyCustomFloat.
template <typename T>
PyObject* PyCustomFloat_Negative(PyObject* self) {
  T x = PyCustomFloat_CustomFloat<T>(self);
  return PyCustomFloat_FromT<T>(-x).release();
}

template <typename T>
PyObject* PyCustomFloat_Add(PyObject* a, PyObject* b) {
  T x, y;
  if (SafeCastToCustomFloat<T>(a, &x) && SafeCastToCustomFloat<T>(b, &y)) {
    return PyCustomFloat_FromT<T>(x + y).release();
  }
  return PyArray_Type.tp_as_number->nb_add(a, b);
}

template <typename T>
PyObject* PyCustomFloat_Subtract(PyObject* a, PyObject* b) {
  T x, y;
  if (SafeCastToCustomFloat<T>(a, &x) && SafeCastToCustomFloat<T>(b, &y)) {
    return PyCustomFloat_FromT<T>(x - y).release();
  }
  return PyArray_Type.tp_as_number->nb_subtract(a, b);
}

template <typename T>
PyObject* PyCustomFloat_Multiply(PyObject* a, PyObject* b) {
  T x, y;
  if (SafeCastToCustomFloat<T>(a, &x) && SafeCastToCustomFloat<T>(b, &y)) {
    return PyCustomFloat_FromT<T>(x * y).release();
  }
  return PyArray_Type.tp_as_number->nb_multiply(a, b);
}

template <typename T>
PyObject* PyCustomFloat_TrueDivide(PyObject* a, PyObject* b) {
  T x, y;
  if (SafeCastToCustomFloat<T>(a, &x) && SafeCastToCustomFloat<T>(b, &y)) {
    return PyCustomFloat_FromT<T>(x / y).release();
  }
  return PyArray_Type.tp_as_number->nb_true_divide(a, b);
}

// Python number methods for PyCustomFloat objects.
template <typename T>
PyNumberMethods CustomFloatTypeDescriptor<T>::number_methods = {
    PyCustomFloat_Add<T>,       // nb_add
    PyCustomFloat_Subtract<T>,  // nb_subtract
    PyCustomFloat_Multiply<T>,  // nb_multiply
    nullptr,                    // nb_remainder
    nullptr,                    // nb_divmod
    nullptr,                    // nb_power
    PyCustomFloat_Negative<T>,  // nb_negative
    nullptr,                    // nb_positive
    nullptr,                    // nb_absolute
    nullptr,                    // nb_nonzero
    nullptr,                    // nb_invert
    nullptr,                    // nb_lshift
    nullptr,                    // nb_rshift
    nullptr,                    // nb_and
    nullptr,                    // nb_xor
    nullptr,                    // nb_or
    PyCustomFloat_Int<T>,       // nb_int
    nullptr,                    // reserved
    PyCustomFloat_Float<T>,     // nb_float

    nullptr,  // nb_inplace_add
    nullptr,  // nb_inplace_subtract
    nullptr,  // nb_inplace_multiply
    nullptr,  // nb_inplace_remainder
    nullptr,  // nb_inplace_power
    nullptr,  // nb_inplace_lshift
    nullptr,  // nb_inplace_rshift
    nullptr,  // nb_inplace_and
    nullptr,  // nb_inplace_xor
    nullptr,  // nb_inplace_or

    nullptr,                      // nb_floor_divide
    PyCustomFloat_TrueDivide<T>,  // nb_true_divide
    nullptr,                      // nb_inplace_floor_divide
    nullptr,                      // nb_inplace_true_divide
    nullptr,                      // nb_index
};

// Constructs a new PyCustomFloat.
template <typename T>
PyObject* PyCustomFloat_New(PyTypeObject* type, PyObject* args,
                            PyObject* kwds) {
  if (kwds && PyDict_Size(kwds)) {
    PyErr_SetString(PyExc_TypeError, "constructor takes no keyword arguments");
    return nullptr;
  }
  Py_ssize_t size = PyTuple_Size(args);
  if (size != 1) {
    PyErr_Format(PyExc_TypeError,
                 "expected number as argument to %s constructor",
                 TypeDescriptor<T>::kTypeName);
    return nullptr;
  }
  PyObject* arg = PyTuple_GetItem(args, 0);

  T value;
  if (PyCustomFloat_Check<T>(arg)) {
    Py_INCREF(arg);
    return arg;
  } else if (CastToCustomFloat<T>(arg, &value)) {
    return PyCustomFloat_FromT<T>(value).release();
  } else if (PyArray_Check(arg)) {
    PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(arg);
    if (PyArray_TYPE(arr) != TypeDescriptor<T>::Dtype()) {
      return PyArray_Cast(arr, TypeDescriptor<T>::Dtype());
    } else {
      Py_INCREF(arg);
      return arg;
    }
  } else if (PyUnicode_Check(arg) || PyBytes_Check(arg)) {
    // Parse float from string, then cast to T.
    PyObject* f = PyFloat_FromString(arg);
    if (CastToCustomFloat<T>(f, &value)) {
      return PyCustomFloat_FromT<T>(value).release();
    }
  }
  PyErr_Format(PyExc_TypeError, "expected number, got %s",
               Py_TYPE(arg)->tp_name);
  return nullptr;
}

// Comparisons on PyCustomFloats.
template <typename T>
PyObject* PyCustomFloat_RichCompare(PyObject* a, PyObject* b, int op) {
  T x, y;
  if (!SafeCastToCustomFloat<T>(a, &x) || !SafeCastToCustomFloat<T>(b, &y)) {
    return PyGenericArrType_Type.tp_richcompare(a, b, op);
  }
  bool result;
  switch (op) {
    case Py_LT:
      result = x < y;
      break;
    case Py_LE:
      result = x <= y;
      break;
    case Py_EQ:
      result = x == y;
      break;
    case Py_NE:
      result = x != y;
      break;
    case Py_GT:
      result = x > y;
      break;
    case Py_GE:
      result = x >= y;
      break;
    default:
      LOG(ERROR) << "Invalid op type " << op;
      result = false;
  }
  return PyBool_FromLong(result);
}

// Implementation of repr() for PyCustomFloat.
template <typename T>
PyObject* PyCustomFloat_Repr(PyObject* self) {
  T x = reinterpret_cast<PyCustomFloat<T>*>(self)->value;
  std::string v = absl::StrCat(static_cast<float>(x));
  return PyUnicode_FromString(v.c_str());
}

// Implementation of str() for PyCustomFloat.
template <typename T>
PyObject* PyCustomFloat_Str(PyObject* self) {
  T x = reinterpret_cast<PyCustomFloat<T>*>(self)->value;
  std::string v = absl::StrCat(static_cast<float>(x));
  return PyUnicode_FromString(v.c_str());
}

// _Py_HashDouble changed its prototype for Python 3.10 so we use an overload to
// handle the two possibilities.
// NOLINTNEXTLINE(clang-diagnostic-unused-function)
inline Py_hash_t HashImpl(Py_hash_t (*hash_double)(PyObject*, double),
                          PyObject* self, double value) {
  return hash_double(self, value);
}

// NOLINTNEXTLINE(clang-diagnostic-unused-function)
inline Py_hash_t HashImpl(Py_hash_t (*hash_double)(double), PyObject* self,
                          double value) {
  return hash_double(value);
}

// Hash function for PyCustomFloat.
template <typename T>
Py_hash_t PyCustomFloat_Hash(PyObject* self) {
  T x = reinterpret_cast<PyCustomFloat<T>*>(self)->value;
  return HashImpl(&_Py_HashDouble, self, static_cast<double>(x));
}

// Python type for PyCustomFloat objects.
template <typename T>
PyTypeObject CustomFloatTypeDescriptor<T>::type = {
    PyVarObject_HEAD_INIT(nullptr, 0) TypeDescriptor<T>::kTypeName,  // tp_name
    sizeof(PyCustomFloat<T>),  // tp_basicsize
    0,                         // tp_itemsize
    nullptr,                   // tp_dealloc
#if PY_VERSION_HEX < 0x03080000
    nullptr,  // tp_print
#else
    0,  // tp_vectorcall_offset
#endif
    nullptr,                                        // tp_getattr
    nullptr,                                        // tp_setattr
    nullptr,                                        // tp_compare / tp_reserved
    PyCustomFloat_Repr<T>,                          // tp_repr
    &CustomFloatTypeDescriptor<T>::number_methods,  // tp_as_number
    nullptr,                                        // tp_as_sequence
    nullptr,                                        // tp_as_mapping
    PyCustomFloat_Hash<T>,                          // tp_hash
    nullptr,                                        // tp_call
    PyCustomFloat_Str<T>,                           // tp_str
    nullptr,                                        // tp_getattro
    nullptr,                                        // tp_setattro
    nullptr,                                        // tp_as_buffer
                                                    // tp_flags
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    TypeDescriptor<T>::kTpDoc,     // tp_doc
    nullptr,                       // tp_traverse
    nullptr,                       // tp_clear
    PyCustomFloat_RichCompare<T>,  // tp_richcompare
    0,                             // tp_weaklistoffset
    nullptr,                       // tp_iter
    nullptr,                       // tp_iternext
    nullptr,                       // tp_methods
    nullptr,                       // tp_members
    nullptr,                       // tp_getset
    nullptr,                       // tp_base
    nullptr,                       // tp_dict
    nullptr,                       // tp_descr_get
    nullptr,                       // tp_descr_set
    0,                             // tp_dictoffset
    nullptr,                       // tp_init
    nullptr,                       // tp_alloc
    PyCustomFloat_New<T>,          // tp_new
    nullptr,                       // tp_free
    nullptr,                       // tp_is_gc
    nullptr,                       // tp_bases
    nullptr,                       // tp_mro
    nullptr,                       // tp_cache
    nullptr,                       // tp_subclasses
    nullptr,                       // tp_weaklist
    nullptr,                       // tp_del
    0,                             // tp_version_tag
};

// Numpy support
template <typename T>
PyArray_ArrFuncs CustomFloatTypeDescriptor<T>::arr_funcs;

template <typename T>
PyArray_Descr CustomFloatTypeDescriptor<T>::npy_descr = {
    PyObject_HEAD_INIT(nullptr)  //
                                 /*typeobj=*/
    (&TypeDescriptor<T>::type),
    /*kind=*/TypeDescriptor<T>::kNpyDescrKind,
    /*type=*/TypeDescriptor<T>::kNpyDescrType,
    /*byteorder=*/TypeDescriptor<T>::kNpyDescrByteorder,
    /*flags=*/NPY_NEEDS_PYAPI | NPY_USE_SETITEM,
    /*type_num=*/0,
    /*elsize=*/sizeof(T),
    /*alignment=*/alignof(T),
    /*subarray=*/nullptr,
    /*fields=*/nullptr,
    /*names=*/nullptr,
    /*f=*/&CustomFloatTypeDescriptor<T>::arr_funcs,
    /*metadata=*/nullptr,
    /*c_metadata=*/nullptr,
    /*hash=*/-1,  // -1 means "not computed yet".
};

// Implementations of NumPy array methods.

template <typename T>
PyObject* NPyCustomFloat_GetItem(void* data, void* arr) {
  T x;
  memcpy(&x, data, sizeof(T));
  return PyFloat_FromDouble(static_cast<float>(x));
}

template <typename T>
int NPyCustomFloat_SetItem(PyObject* item, void* data, void* arr) {
  T x;
  if (!CastToCustomFloat<T>(item, &x)) {
    PyErr_Format(PyExc_TypeError, "expected number, got %s",
                 Py_TYPE(item)->tp_name);
    return -1;
  }
  memcpy(data, &x, sizeof(T));
  return 0;
}

inline void ByteSwap16(void* value) {
  char* p = reinterpret_cast<char*>(value);
  std::swap(p[0], p[1]);
}

template <typename T>
int NPyCustomFloat_Compare(const void* a, const void* b, void* arr) {
  T x;
  memcpy(&x, a, sizeof(T));

  T y;
  memcpy(&y, b, sizeof(T));
  float fy(y);
  float fx(x);

  if (fx < fy) {
    return -1;
  }
  if (fy < fx) {
    return 1;
  }
  // NaNs sort to the end.
  if (!Eigen::numext::isnan(fx) && Eigen::numext::isnan(fy)) {
    return -1;
  }
  if (Eigen::numext::isnan(fx) && !Eigen::numext::isnan(fy)) {
    return 1;
  }
  return 0;
}

template <typename T>
void NPyCustomFloat_CopySwapN(void* dstv, npy_intp dstride, void* srcv,
                              npy_intp sstride, npy_intp n, int swap,
                              void* arr) {
  static_assert(sizeof(T) == sizeof(int16_t) || sizeof(T) == sizeof(int8_t),
                "Not supported");
  char* dst = reinterpret_cast<char*>(dstv);
  char* src = reinterpret_cast<char*>(srcv);
  if (!src) {
    return;
  }
  if (swap && sizeof(T) == sizeof(int16_t)) {
    for (npy_intp i = 0; i < n; i++) {
      char* r = dst + dstride * i;
      memcpy(r, src + sstride * i, sizeof(T));
      ByteSwap16(r);
    }
  } else if (dstride == sizeof(T) && sstride == sizeof(T)) {
    memcpy(dst, src, n * sizeof(T));
  } else {
    for (npy_intp i = 0; i < n; i++) {
      memcpy(dst + dstride * i, src + sstride * i, sizeof(T));
    }
  }
}

template <typename T>
void NPyCustomFloat_CopySwap(void* dst, void* src, int swap, void* arr) {
  if (!src) {
    return;
  }
  memcpy(dst, src, sizeof(T));
  static_assert(sizeof(T) == sizeof(int16_t) || sizeof(T) == sizeof(int8_t),
                "Not supported");
  if (swap && sizeof(T) == sizeof(int16_t)) {
    ByteSwap16(dst);
  }
}

template <typename T>
npy_bool NPyCustomFloat_NonZero(void* data, void* arr) {
  T x;
  memcpy(&x, data, sizeof(x));
  return x != static_cast<T>(0);
}

template <typename T>
int NPyCustomFloat_Fill(void* buffer_raw, npy_intp length, void* ignored) {
  T* const buffer = reinterpret_cast<T*>(buffer_raw);
  const float start(buffer[0]);
  const float delta = static_cast<float>(buffer[1]) - start;
  for (npy_intp i = 2; i < length; ++i) {
    buffer[i] = static_cast<T>(start + i * delta);
  }
  return 0;
}

template <typename T>
void NPyCustomFloat_DotFunc(void* ip1, npy_intp is1, void* ip2, npy_intp is2,
                            void* op, npy_intp n, void* arr) {
  char* c1 = reinterpret_cast<char*>(ip1);
  char* c2 = reinterpret_cast<char*>(ip2);
  float acc = 0.0f;
  for (npy_intp i = 0; i < n; ++i) {
    T* const b1 = reinterpret_cast<T*>(c1);
    T* const b2 = reinterpret_cast<T*>(c2);
    acc += static_cast<float>(*b1) * static_cast<float>(*b2);
    c1 += is1;
    c2 += is2;
  }
  T* out = reinterpret_cast<T*>(op);
  *out = static_cast<T>(acc);
}

template <typename T>
int NPyCustomFloat_CompareFunc(const void* v1, const void* v2, void* arr) {
  T b1 = *reinterpret_cast<const T*>(v1);
  T b2 = *reinterpret_cast<const T*>(v2);
  if (b1 < b2) {
    return -1;
  }
  if (b1 > b2) {
    return 1;
  }
  return 0;
}

template <typename T>
int NPyCustomFloat_ArgMaxFunc(void* data, npy_intp n, npy_intp* max_ind,
                              void* arr) {
  const T* bdata = reinterpret_cast<const T*>(data);
  // Start with a max_val of NaN, this results in the first iteration preferring
  // bdata[0].
  float max_val = std::numeric_limits<float>::quiet_NaN();
  for (npy_intp i = 0; i < n; ++i) {
    // This condition is chosen so that NaNs are always considered "max".
    if (!(static_cast<float>(bdata[i]) <= max_val)) {
      max_val = static_cast<float>(bdata[i]);
      *max_ind = i;
      // NumPy stops at the first NaN.
      if (Eigen::numext::isnan(max_val)) {
        break;
      }
    }
  }
  return 0;
}

template <typename T>
int NPyCustomFloat_ArgMinFunc(void* data, npy_intp n, npy_intp* min_ind,
                              void* arr) {
  const T* bdata = reinterpret_cast<const T*>(data);
  float min_val = std::numeric_limits<float>::quiet_NaN();
  // Start with a min_val of NaN, this results in the first iteration preferring
  // bdata[0].
  for (npy_intp i = 0; i < n; ++i) {
    // This condition is chosen so that NaNs are always considered "min".
    if (!(static_cast<float>(bdata[i]) >= min_val)) {
      min_val = static_cast<float>(bdata[i]);
      *min_ind = i;
      // NumPy stops at the first NaN.
      if (Eigen::numext::isnan(min_val)) {
        break;
      }
    }
  }
  return 0;
}

template <>
struct TypeDescriptor<unsigned char> {
  typedef unsigned char T;
  static int Dtype() { return NPY_UBYTE; }
};

template <>
struct TypeDescriptor<unsigned short> {  // NOLINT
  typedef unsigned short T;              // NOLINT
  static int Dtype() { return NPY_USHORT; }
};

// We register "int", "long", and "long long" types for portability across
// Linux, where "int" and "long" are the same type, and Windows, where "long"
// and "longlong" are the same type.
template <>
struct TypeDescriptor<unsigned int> {
  typedef unsigned int T;
  static int Dtype() { return NPY_UINT; }
};

template <>
struct TypeDescriptor<unsigned long> {  // NOLINT
  typedef unsigned long T;              // NOLINT
  static int Dtype() { return NPY_ULONG; }
};

template <>
struct TypeDescriptor<unsigned long long> {  // NOLINT
  typedef unsigned long long T;              // NOLINT
  static int Dtype() { return NPY_ULONGLONG; }
};

template <>
struct TypeDescriptor<signed char> {
  typedef signed char T;
  static int Dtype() { return NPY_BYTE; }
};

template <>
struct TypeDescriptor<short> {  // NOLINT
  typedef short T;              // NOLINT
  static int Dtype() { return NPY_SHORT; }
};

template <>
struct TypeDescriptor<int> {
  typedef int T;
  static int Dtype() { return NPY_INT; }
};

template <>
struct TypeDescriptor<long> {  // NOLINT
  typedef long T;              // NOLINT
  static int Dtype() { return NPY_LONG; }
};

template <>
struct TypeDescriptor<long long> {  // NOLINT
  typedef long long T;              // NOLINT
  static int Dtype() { return NPY_LONGLONG; }
};

template <>
struct TypeDescriptor<bool> {
  typedef unsigned char T;
  static int Dtype() { return NPY_BOOL; }
};

template <>
struct TypeDescriptor<Eigen::half> {
  typedef Eigen::half T;
  static int Dtype() { return NPY_HALF; }
};

template <>
struct TypeDescriptor<float> {
  typedef float T;
  static int Dtype() { return NPY_FLOAT; }
};

template <>
struct TypeDescriptor<double> {
  typedef double T;
  static int Dtype() { return NPY_DOUBLE; }
};

template <>
struct TypeDescriptor<long double> {
  typedef long double T;
  static int Dtype() { return NPY_LONGDOUBLE; }
};

template <>
struct TypeDescriptor<std::complex<float>> {
  typedef std::complex<float> T;
  static int Dtype() { return NPY_CFLOAT; }
};

template <>
struct TypeDescriptor<std::complex<double>> {
  typedef std::complex<double> T;
  static int Dtype() { return NPY_CDOUBLE; }
};

template <>
struct TypeDescriptor<std::complex<long double>> {
  typedef std::complex<long double> T;
  static int Dtype() { return NPY_CLONGDOUBLE; }
};

template <typename T>
float CastToFloat(T value) {
  return static_cast<float>(value);
}

template <typename T>
float CastToFloat(std::complex<T> value) {
  return CastToFloat(value.real());
}

// Performs a NumPy array cast from type 'From' to 'To'.
template <typename From, typename To>
void NPyCast(void* from_void, void* to_void, npy_intp n, void* fromarr,
             void* toarr) {
  const auto* from =
      reinterpret_cast<typename TypeDescriptor<From>::T*>(from_void);
  auto* to = reinterpret_cast<typename TypeDescriptor<To>::T*>(to_void);
  for (npy_intp i = 0; i < n; ++i) {
    to[i] = static_cast<typename TypeDescriptor<To>::T>(
        static_cast<To>(CastToFloat(from[i])));
  }
}

// Registers a cast between T (a reduced float) and type 'OtherT'. 'numpy_type'
// is the NumPy type corresponding to 'OtherT'.
template <typename T, typename OtherT>
bool RegisterCustomFloatCast(int numpy_type = TypeDescriptor<OtherT>::Dtype()) {
  PyArray_Descr* descr = PyArray_DescrFromType(numpy_type);
  if (PyArray_RegisterCastFunc(descr, TypeDescriptor<T>::Dtype(),
                               NPyCast<OtherT, T>) < 0) {
    return false;
  }
  if (PyArray_RegisterCastFunc(&CustomFloatTypeDescriptor<T>::npy_descr,
                               numpy_type, NPyCast<T, OtherT>) < 0) {
    return false;
  }
  return true;
}

template <typename T>
bool RegisterCasts() {
  if (!RegisterCustomFloatCast<T, Eigen::half>(NPY_HALF)) {
    return false;
  }

  if (!RegisterCustomFloatCast<T, float>(NPY_FLOAT)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, double>(NPY_DOUBLE)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, long double>(NPY_LONGDOUBLE)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, bool>(NPY_BOOL)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, unsigned char>(NPY_UBYTE)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, unsigned short>(NPY_USHORT)) {  // NOLINT
    return false;
  }
  if (!RegisterCustomFloatCast<T, unsigned int>(NPY_UINT)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, unsigned long>(NPY_ULONG)) {  // NOLINT
    return false;
  }
  if (!RegisterCustomFloatCast<T, unsigned long long>(  // NOLINT
          NPY_ULONGLONG)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, signed char>(NPY_BYTE)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, short>(NPY_SHORT)) {  // NOLINT
    return false;
  }
  if (!RegisterCustomFloatCast<T, int>(NPY_INT)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, long>(NPY_LONG)) {  // NOLINT
    return false;
  }
  if (!RegisterCustomFloatCast<T, long long>(NPY_LONGLONG)) {  // NOLINT
    return false;
  }
  // Following the numpy convention. imag part is dropped when converting to
  // float.
  if (!RegisterCustomFloatCast<T, std::complex<float>>(NPY_CFLOAT)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, std::complex<double>>(NPY_CDOUBLE)) {
    return false;
  }
  if (!RegisterCustomFloatCast<T, std::complex<long double>>(NPY_CLONGDOUBLE)) {
    return false;
  }

  // Safe casts from T to other types
  if (PyArray_RegisterCanCast(&TypeDescriptor<T>::npy_descr, NPY_FLOAT,
                              NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(&TypeDescriptor<T>::npy_descr, NPY_DOUBLE,
                              NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(&TypeDescriptor<T>::npy_descr, NPY_LONGDOUBLE,
                              NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(&TypeDescriptor<T>::npy_descr, NPY_CFLOAT,
                              NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(&TypeDescriptor<T>::npy_descr, NPY_CDOUBLE,
                              NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(&TypeDescriptor<T>::npy_descr, NPY_CLONGDOUBLE,
                              NPY_NOSCALAR) < 0) {
    return false;
  }

  // Safe casts to T from other types
  if (PyArray_RegisterCanCast(PyArray_DescrFromType(NPY_BOOL),
                              TypeDescriptor<T>::Dtype(), NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(PyArray_DescrFromType(NPY_UBYTE),
                              TypeDescriptor<T>::Dtype(), NPY_NOSCALAR) < 0) {
    return false;
  }
  if (PyArray_RegisterCanCast(PyArray_DescrFromType(NPY_BYTE),
                              TypeDescriptor<T>::Dtype(), NPY_NOSCALAR) < 0) {
    return false;
  }

  return true;
}

template <typename InType, typename OutType, typename Functor>
struct UnaryUFunc {
  static std::vector<int> Types() {
    return {TypeDescriptor<InType>::Dtype(), TypeDescriptor<OutType>::Dtype()};
  }
  static void Call(char** args, const npy_intp* dimensions,
                   const npy_intp* steps, void* data) {
    const char* i0 = args[0];
    char* o = args[1];
    for (npy_intp k = 0; k < *dimensions; k++) {
      auto x = *reinterpret_cast<const typename TypeDescriptor<InType>::T*>(i0);
      *reinterpret_cast<typename TypeDescriptor<OutType>::T*>(o) = Functor()(x);
      i0 += steps[0];
      o += steps[1];
    }
  }
};

template <typename InType, typename OutType, typename OutType2,
          typename Functor>
struct UnaryUFunc2 {
  static std::vector<int> Types() {
    return {TypeDescriptor<InType>::Dtype(), TypeDescriptor<OutType>::Dtype(),
            TypeDescriptor<OutType2>::Dtype()};
  }
  static void Call(char** args, const npy_intp* dimensions,
                   const npy_intp* steps, void* data) {
    const char* i0 = args[0];
    char* o0 = args[1];
    char* o1 = args[2];
    for (npy_intp k = 0; k < *dimensions; k++) {
      auto x = *reinterpret_cast<const typename TypeDescriptor<InType>::T*>(i0);
      std::tie(*reinterpret_cast<typename TypeDescriptor<OutType>::T*>(o0),
               *reinterpret_cast<typename TypeDescriptor<OutType2>::T*>(o1)) =
          Functor()(x);
      i0 += steps[0];
      o0 += steps[1];
      o1 += steps[2];
    }
  }
};

template <typename InType, typename OutType, typename Functor>
struct BinaryUFunc {
  static std::vector<int> Types() {
    return {TypeDescriptor<InType>::Dtype(), TypeDescriptor<InType>::Dtype(),
            TypeDescriptor<OutType>::Dtype()};
  }
  static void Call(char** args, const npy_intp* dimensions,
                   const npy_intp* steps, void* data) {
    const char* i0 = args[0];
    const char* i1 = args[1];
    char* o = args[2];
    for (npy_intp k = 0; k < *dimensions; k++) {
      auto x = *reinterpret_cast<const typename TypeDescriptor<InType>::T*>(i0);
      auto y = *reinterpret_cast<const typename TypeDescriptor<InType>::T*>(i1);
      *reinterpret_cast<typename TypeDescriptor<OutType>::T*>(o) =
          Functor()(x, y);
      i0 += steps[0];
      i1 += steps[1];
      o += steps[2];
    }
  }
};

template <typename InType, typename InType2, typename OutType, typename Functor>
struct BinaryUFunc2 {
  static std::vector<int> Types() {
    return {TypeDescriptor<InType>::Dtype(), TypeDescriptor<InType2>::Dtype(),
            TypeDescriptor<OutType>::Dtype()};
  }
  static void Call(char** args, const npy_intp* dimensions,
                   const npy_intp* steps, void* data) {
    const char* i0 = args[0];
    const char* i1 = args[1];
    char* o = args[2];
    for (npy_intp k = 0; k < *dimensions; k++) {
      auto x = *reinterpret_cast<const typename TypeDescriptor<InType>::T*>(i0);
      auto y =
          *reinterpret_cast<const typename TypeDescriptor<InType2>::T*>(i1);
      *reinterpret_cast<typename TypeDescriptor<OutType>::T*>(o) =
          Functor()(x, y);
      i0 += steps[0];
      i1 += steps[1];
      o += steps[2];
    }
  }
};

template <typename UFunc, typename CustomFloatT>
bool RegisterUFunc(PyObject* numpy, const char* name) {
  std::vector<int> types = UFunc::Types();
  PyUFuncGenericFunction fn =
      reinterpret_cast<PyUFuncGenericFunction>(UFunc::Call);
  Safe_PyObjectPtr ufunc_obj = make_safe(PyObject_GetAttrString(numpy, name));
  if (!ufunc_obj) {
    return false;
  }
  PyUFuncObject* ufunc = reinterpret_cast<PyUFuncObject*>(ufunc_obj.get());
  if (static_cast<int>(types.size()) != ufunc->nargs) {
    PyErr_Format(PyExc_AssertionError,
                 "ufunc %s takes %d arguments, loop takes %lu", name,
                 ufunc->nargs, types.size());
    return false;
  }
  if (PyUFunc_RegisterLoopForType(ufunc, TypeDescriptor<CustomFloatT>::Dtype(),
                                  fn, const_cast<int*>(types.data()),
                                  nullptr) < 0) {
    return false;
  }
  return true;
}

namespace ufuncs {

template <typename T>
struct Add {
  T operator()(T a, T b) { return a + b; }
};
template <typename T>
struct Subtract {
  T operator()(T a, T b) { return a - b; }
};
template <typename T>
struct Multiply {
  T operator()(T a, T b) { return a * b; }
};
template <typename T>
struct TrueDivide {
  T operator()(T a, T b) { return a / b; }
};

inline std::pair<float, float> divmod(float a, float b) {
  if (b == 0.0f) {
    float nan = std::numeric_limits<float>::quiet_NaN();
    return {nan, nan};
  }
  float mod = std::fmod(a, b);
  float div = (a - mod) / b;
  if (mod != 0.0f) {
    if ((b < 0.0f) != (mod < 0.0f)) {
      mod += b;
      div -= 1.0f;
    }
  } else {
    mod = std::copysign(0.0f, b);
  }

  float floordiv;
  if (div != 0.0f) {
    floordiv = std::floor(div);
    if (div - floordiv > 0.5f) {
      floordiv += 1.0f;
    }
  } else {
    floordiv = std::copysign(0.0f, a / b);
  }
  return {floordiv, mod};
}

template <typename T>
struct FloorDivide {
  T operator()(T a, T b) {
    return T(divmod(static_cast<float>(a), static_cast<float>(b)).first);
  }
};
template <typename T>
struct Remainder {
  T operator()(T a, T b) {
    return T(divmod(static_cast<float>(a), static_cast<float>(b)).second);
  }
};
template <typename T>
struct DivmodUFunc {
  static std::vector<int> Types() {
    return {TypeDescriptor<T>::Dtype(), TypeDescriptor<T>::Dtype(),
            TypeDescriptor<T>::Dtype(), TypeDescriptor<T>::Dtype()};
  }
  static void Call(char** args, npy_intp* dimensions, npy_intp* steps,
                   void* data) {
    const char* i0 = args[0];
    const char* i1 = args[1];
    char* o0 = args[2];
    char* o1 = args[3];
    for (npy_intp k = 0; k < *dimensions; k++) {
      T x = *reinterpret_cast<const T*>(i0);
      T y = *reinterpret_cast<const T*>(i1);
      float floordiv, mod;
      std::tie(floordiv, mod) =
          divmod(static_cast<float>(x), static_cast<float>(y));
      *reinterpret_cast<T*>(o0) = T(floordiv);
      *reinterpret_cast<T*>(o1) = T(mod);
      i0 += steps[0];
      i1 += steps[1];
      o0 += steps[2];
      o1 += steps[3];
    }
  }
};
template <typename T>
struct Fmod {
  T operator()(T a, T b) {
    return T(std::fmod(static_cast<float>(a), static_cast<float>(b)));
  }
};
template <typename T>
struct Negative {
  T operator()(T a) { return -a; }
};
template <typename T>
struct Positive {
  T operator()(T a) { return a; }
};
template <typename T>
struct Power {
  T operator()(T a, T b) {
    return T(std::pow(static_cast<float>(a), static_cast<float>(b)));
  }
};
template <typename T>
struct Abs {
  T operator()(T a) { return T(std::abs(static_cast<float>(a))); }
};
template <typename T>
struct Cbrt {
  T operator()(T a) { return T(std::cbrt(static_cast<float>(a))); }
};
template <typename T>
struct Ceil {
  T operator()(T a) { return T(std::ceil(static_cast<float>(a))); }
};
template <typename T>
struct CopySign;

template <typename T>
struct Exp {
  T operator()(T a) { return T(std::exp(static_cast<float>(a))); }
};
template <typename T>
struct Exp2 {
  T operator()(T a) { return T(std::exp2(static_cast<float>(a))); }
};
template <typename T>
struct Expm1 {
  T operator()(T a) { return T(std::expm1(static_cast<float>(a))); }
};
template <typename T>
struct Floor {
  T operator()(T a) { return T(std::floor(static_cast<float>(a))); }
};
template <typename T>
struct Frexp {
  std::pair<T, int> operator()(T a) {
    int exp;
    float f = std::frexp(static_cast<float>(a), &exp);
    return {T(f), exp};
  }
};
template <typename T>
struct Heaviside {
  T operator()(T bx, T h0) {
    float x = static_cast<float>(bx);
    if (Eigen::numext::isnan(x)) {
      return bx;
    }
    if (x < 0) {
      return T(0.0f);
    }
    if (x > 0) {
      return T(1.0f);
    }
    return h0;  // x == 0
  }
};
template <typename T>
struct Conjugate {
  T operator()(T a) { return a; }
};
template <typename T>
struct IsFinite {
  bool operator()(T a) { return std::isfinite(static_cast<float>(a)); }
};
template <typename T>
struct IsInf {
  bool operator()(T a) { return std::isinf(static_cast<float>(a)); }
};
template <typename T>
struct IsNan {
  bool operator()(T a) { return Eigen::numext::isnan(static_cast<float>(a)); }
};
template <typename T>
struct Ldexp {
  T operator()(T a, int exp) {
    return T(std::ldexp(static_cast<float>(a), exp));
  }
};
template <typename T>
struct Log {
  T operator()(T a) { return T(std::log(static_cast<float>(a))); }
};
template <typename T>
struct Log2 {
  T operator()(T a) { return T(std::log2(static_cast<float>(a))); }
};
template <typename T>
struct Log10 {
  T operator()(T a) { return T(std::log10(static_cast<float>(a))); }
};
template <typename T>
struct Log1p {
  T operator()(T a) { return T(std::log1p(static_cast<float>(a))); }
};
template <typename T>
struct LogAddExp {
  T operator()(T bx, T by) {
    float x = static_cast<float>(bx);
    float y = static_cast<float>(by);
    if (x == y) {
      // Handles infinities of the same sign.
      return T(x + std::log(2.0f));
    }
    float out = std::numeric_limits<float>::quiet_NaN();
    if (x > y) {
      out = x + std::log1p(std::exp(y - x));
    } else if (x < y) {
      out = y + std::log1p(std::exp(x - y));
    }
    return T(out);
  }
};
template <typename T>
struct LogAddExp2 {
  T operator()(T bx, T by) {
    float x = static_cast<float>(bx);
    float y = static_cast<float>(by);
    if (x == y) {
      // Handles infinities of the same sign.
      return T(x + 1.0f);
    }
    float out = std::numeric_limits<float>::quiet_NaN();
    if (x > y) {
      out = x + std::log1p(std::exp2(y - x)) / std::log(2.0f);
    } else if (x < y) {
      out = y + std::log1p(std::exp2(x - y)) / std::log(2.0f);
    }
    return T(out);
  }
};
template <typename T>
struct Modf {
  std::pair<T, T> operator()(T a) {
    float integral;
    float f = std::modf(static_cast<float>(a), &integral);
    return {T(f), T(integral)};
  }
};

template <typename T>
struct Reciprocal {
  T operator()(T a) { return T(1.f / static_cast<float>(a)); }
};
template <typename T>
struct Rint {
  T operator()(T a) { return T(std::rint(static_cast<float>(a))); }
};
template <typename T>
struct Sign {
  T operator()(T a) {
    float f(a);
    if (f < 0) {
      return T(-1);
    }
    if (f > 0) {
      return T(1);
    }
    return a;
  }
};
template <typename T>
struct SignBit {
  bool operator()(T a) { return std::signbit(static_cast<float>(a)); }
};
template <typename T>
struct Sqrt {
  T operator()(T a) { return T(std::sqrt(static_cast<float>(a))); }
};
template <typename T>
struct Square {
  T operator()(T a) {
    float f(a);
    return T(f * f);
  }
};
template <typename T>
struct Trunc {
  T operator()(T a) { return T(std::trunc(static_cast<float>(a))); }
};

// Trigonometric functions
template <typename T>
struct Sin {
  T operator()(T a) { return T(std::sin(static_cast<float>(a))); }
};
template <typename T>
struct Cos {
  T operator()(T a) { return T(std::cos(static_cast<float>(a))); }
};
template <typename T>
struct Tan {
  T operator()(T a) { return T(std::tan(static_cast<float>(a))); }
};
template <typename T>
struct Arcsin {
  T operator()(T a) { return T(std::asin(static_cast<float>(a))); }
};
template <typename T>
struct Arccos {
  T operator()(T a) { return T(std::acos(static_cast<float>(a))); }
};
template <typename T>
struct Arctan {
  T operator()(T a) { return T(std::atan(static_cast<float>(a))); }
};
template <typename T>
struct Arctan2 {
  T operator()(T a, T b) {
    return T(std::atan2(static_cast<float>(a), static_cast<float>(b)));
  }
};
template <typename T>
struct Hypot {
  T operator()(T a, T b) {
    return T(std::hypot(static_cast<float>(a), static_cast<float>(b)));
  }
};
template <typename T>
struct Sinh {
  T operator()(T a) { return T(std::sinh(static_cast<float>(a))); }
};
template <typename T>
struct Cosh {
  T operator()(T a) { return T(std::cosh(static_cast<float>(a))); }
};
template <typename T>
struct Tanh {
  T operator()(T a) { return T(std::tanh(static_cast<float>(a))); }
};
template <typename T>
struct Arcsinh {
  T operator()(T a) { return T(std::asinh(static_cast<float>(a))); }
};
template <typename T>
struct Arccosh {
  T operator()(T a) { return T(std::acosh(static_cast<float>(a))); }
};
template <typename T>
struct Arctanh {
  T operator()(T a) { return T(std::atanh(static_cast<float>(a))); }
};
template <typename T>
struct Deg2rad {
  T operator()(T a) {
    static constexpr float radians_per_degree = M_PI / 180.0f;
    return T(static_cast<float>(a) * radians_per_degree);
  }
};
template <typename T>
struct Rad2deg {
  T operator()(T a) {
    static constexpr float degrees_per_radian = 180.0f / M_PI;
    return T(static_cast<float>(a) * degrees_per_radian);
  }
};

template <typename T>
struct Eq {
  npy_bool operator()(T a, T b) { return a == b; }
};
template <typename T>
struct Ne {
  npy_bool operator()(T a, T b) { return a != b; }
};
template <typename T>
struct Lt {
  npy_bool operator()(T a, T b) { return a < b; }
};
template <typename T>
struct Gt {
  npy_bool operator()(T a, T b) { return a > b; }
};
template <typename T>
struct Le {
  npy_bool operator()(T a, T b) { return a <= b; }
};
template <typename T>
struct Ge {
  npy_bool operator()(T a, T b) { return a >= b; }
};
template <typename T>
struct Maximum {
  T operator()(T a, T b) {
    float fa(a), fb(b);
    return Eigen::numext::isnan(fa) || fa > fb ? a : b;
  }
};
template <typename T>
struct Minimum {
  T operator()(T a, T b) {
    float fa(a), fb(b);
    return Eigen::numext::isnan(fa) || fa < fb ? a : b;
  }
};
template <typename T>
struct Fmax {
  T operator()(T a, T b) {
    float fa(a), fb(b);
    return Eigen::numext::isnan(fb) || fa > fb ? a : b;
  }
};
template <typename T>
struct Fmin {
  T operator()(T a, T b) {
    float fa(a), fb(b);
    return Eigen::numext::isnan(fb) || fa < fb ? a : b;
  }
};

template <typename T>
struct LogicalNot {
  npy_bool operator()(T a) { return !static_cast<bool>(a); }
};
template <typename T>
struct LogicalAnd {
  npy_bool operator()(T a, T b) {
    return static_cast<bool>(a) && static_cast<bool>(b);
  }
};
template <typename T>
struct LogicalOr {
  npy_bool operator()(T a, T b) {
    return static_cast<bool>(a) || static_cast<bool>(b);
  }
};
template <typename T>
struct LogicalXor {
  npy_bool operator()(T a, T b) {
    return static_cast<bool>(a) ^ static_cast<bool>(b);
  }
};

template <typename T>
struct NextAfter;

template <typename T>
struct Spacing {
  T operator()(T x) {
    // Compute the distance between the input and the next number with greater
    // magnitude. The result should have the sign of the input.
    T away(std::copysign(std::numeric_limits<float>::infinity(),
                         static_cast<float>(x)));
    return NextAfter<T>()(x, away) - x;
  }
};

template <typename T>
bool RegisterUFuncs(PyObject* numpy) {
  bool ok =
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Add<T>>, T>(numpy, "add") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Subtract<T>>, T>(numpy,
                                                               "subtract") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Multiply<T>>, T>(numpy,
                                                               "multiply") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::TrueDivide<T>>, T>(numpy,
                                                                 "divide") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::LogAddExp<T>>, T>(numpy,
                                                                "logaddexp") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::LogAddExp2<T>>, T>(
          numpy, "logaddexp2") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Negative<T>>, T>(numpy,
                                                              "negative") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Positive<T>>, T>(numpy,
                                                              "positive") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::TrueDivide<T>>, T>(
          numpy, "true_divide") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::FloorDivide<T>>, T>(
          numpy, "floor_divide") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Power<T>>, T>(numpy, "power") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Remainder<T>>, T>(numpy,
                                                                "remainder") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Remainder<T>>, T>(numpy, "mod") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Fmod<T>>, T>(numpy, "fmod") &&
      RegisterUFunc<ufuncs::DivmodUFunc<T>, T>(numpy, "divmod") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Abs<T>>, T>(numpy, "absolute") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Abs<T>>, T>(numpy, "fabs") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Rint<T>>, T>(numpy, "rint") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Sign<T>>, T>(numpy, "sign") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Heaviside<T>>, T>(numpy,
                                                                "heaviside") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Conjugate<T>>, T>(numpy,
                                                               "conjugate") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Exp<T>>, T>(numpy, "exp") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Exp2<T>>, T>(numpy, "exp2") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Expm1<T>>, T>(numpy, "expm1") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Log<T>>, T>(numpy, "log") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Log2<T>>, T>(numpy, "log2") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Log10<T>>, T>(numpy, "log10") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Log1p<T>>, T>(numpy, "log1p") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Sqrt<T>>, T>(numpy, "sqrt") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Square<T>>, T>(numpy, "square") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Cbrt<T>>, T>(numpy, "cbrt") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Reciprocal<T>>, T>(numpy,
                                                                "reciprocal") &&

      // Trigonometric functions
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Sin<T>>, T>(numpy, "sin") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Cos<T>>, T>(numpy, "cos") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Tan<T>>, T>(numpy, "tan") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Arcsin<T>>, T>(numpy, "arcsin") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Arccos<T>>, T>(numpy, "arccos") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Arctan<T>>, T>(numpy, "arctan") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Arctan2<T>>, T>(numpy,
                                                              "arctan2") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Hypot<T>>, T>(numpy, "hypot") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Sinh<T>>, T>(numpy, "sinh") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Cosh<T>>, T>(numpy, "cosh") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Tanh<T>>, T>(numpy, "tanh") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Arcsinh<T>>, T>(numpy,
                                                             "arcsinh") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Arccosh<T>>, T>(numpy,
                                                             "arccosh") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Arctanh<T>>, T>(numpy,
                                                             "arctanh") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Deg2rad<T>>, T>(numpy,
                                                             "deg2rad") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Rad2deg<T>>, T>(numpy,
                                                             "rad2deg") &&

      // Comparison functions
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::Eq<T>>, T>(numpy, "equal") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::Ne<T>>, T>(numpy,
                                                            "not_equal") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::Lt<T>>, T>(numpy, "less") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::Gt<T>>, T>(numpy, "greater") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::Le<T>>, T>(numpy,
                                                            "less_equal") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::Ge<T>>, T>(numpy,
                                                            "greater_equal") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Maximum<T>>, T>(numpy,
                                                              "maximum") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Minimum<T>>, T>(numpy,
                                                              "minimum") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Fmax<T>>, T>(numpy, "fmax") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::Fmin<T>>, T>(numpy, "fmin") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::LogicalAnd<T>>, T>(
          numpy, "logical_and") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::LogicalOr<T>>, T>(
          numpy, "logical_or") &&
      RegisterUFunc<BinaryUFunc<T, bool, ufuncs::LogicalXor<T>>, T>(
          numpy, "logical_xor") &&
      RegisterUFunc<UnaryUFunc<T, bool, ufuncs::LogicalNot<T>>, T>(
          numpy, "logical_not") &&

      // Floating point functions
      RegisterUFunc<UnaryUFunc<T, bool, ufuncs::IsFinite<T>>, T>(numpy,
                                                                 "isfinite") &&
      RegisterUFunc<UnaryUFunc<T, bool, ufuncs::IsInf<T>>, T>(numpy, "isinf") &&
      RegisterUFunc<UnaryUFunc<T, bool, ufuncs::IsNan<T>>, T>(numpy, "isnan") &&
      RegisterUFunc<UnaryUFunc<T, bool, ufuncs::SignBit<T>>, T>(numpy,
                                                                "signbit") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::CopySign<T>>, T>(numpy,
                                                               "copysign") &&
      RegisterUFunc<UnaryUFunc2<T, T, T, ufuncs::Modf<T>>, T>(numpy, "modf") &&
      RegisterUFunc<BinaryUFunc2<T, int, T, ufuncs::Ldexp<T>>, T>(numpy,
                                                                  "ldexp") &&
      RegisterUFunc<UnaryUFunc2<T, T, int, ufuncs::Frexp<T>>, T>(numpy,
                                                                 "frexp") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Floor<T>>, T>(numpy, "floor") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Ceil<T>>, T>(numpy, "ceil") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Trunc<T>>, T>(numpy, "trunc") &&
      RegisterUFunc<BinaryUFunc<T, T, ufuncs::NextAfter<T>>, T>(numpy,
                                                                "nextafter") &&
      RegisterUFunc<UnaryUFunc<T, T, ufuncs::Spacing<T>>, T>(numpy, "spacing");

  return ok;
}

}  // namespace ufuncs

template <typename T>
bool RegisterNumpyDtype(PyObject* numpy) {
  // If another module (presumably either TF or JAX) has registered a bfloat16
  // type, use it. We don't want two bfloat16 types if we can avoid it since it
  // leads to confusion if we have two different types with the same name. This
  // assumes that the other module has a sufficiently complete bfloat16
  // implementation. The only known NumPy bfloat16 extension at the time of
  // writing is this one (distributed in TF and JAX).
  // TODO(phawkins): distribute the bfloat16 extension as its own pip package,
  // so we can unambiguously refer to a single canonical definition of bfloat16.
  int typenum =
      PyArray_TypeNumFromName(const_cast<char*>(TypeDescriptor<T>::kTypeName));
  if (typenum != NPY_NOTYPE) {
    PyArray_Descr* descr = PyArray_DescrFromType(typenum);
    // The test for an argmax function here is to verify that the
    // bfloat16 implementation is sufficiently new, and, say, not from
    // an older version of TF or JAX.
    if (descr && descr->f && descr->f->argmax) {
      TypeDescriptor<T>::npy_type = typenum;
      TypeDescriptor<T>::type_ptr = descr->typeobj;
      return true;
    }
  }

  TypeDescriptor<T>::type.tp_base = &PyGenericArrType_Type;

  if (PyType_Ready(&TypeDescriptor<T>::type) < 0) {
    return false;
  }

  // Initializes the NumPy descriptor.
  PyArray_ArrFuncs& arr_funcs = CustomFloatTypeDescriptor<T>::arr_funcs;
  PyArray_InitArrFuncs(&arr_funcs);
  arr_funcs.getitem = NPyCustomFloat_GetItem<T>;
  arr_funcs.setitem = NPyCustomFloat_SetItem<T>;
  arr_funcs.compare = NPyCustomFloat_Compare<T>;
  arr_funcs.copyswapn = NPyCustomFloat_CopySwapN<T>;
  arr_funcs.copyswap = NPyCustomFloat_CopySwap<T>;
  arr_funcs.nonzero = NPyCustomFloat_NonZero<T>;
  arr_funcs.fill = NPyCustomFloat_Fill<T>;
  arr_funcs.dotfunc = NPyCustomFloat_DotFunc<T>;
  arr_funcs.compare = NPyCustomFloat_CompareFunc<T>;
  arr_funcs.argmax = NPyCustomFloat_ArgMaxFunc<T>;
  arr_funcs.argmin = NPyCustomFloat_ArgMinFunc<T>;

#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
  Py_TYPE(&CustomFloatTypeDescriptor<T>::npy_descr) = &PyArrayDescr_Type;
#else
  Py_SET_TYPE(&CustomFloatTypeDescriptor<T>::npy_descr, &PyArrayDescr_Type);
#endif
  TypeDescriptor<T>::npy_type =
      PyArray_RegisterDataType(&CustomFloatTypeDescriptor<T>::npy_descr);
  TypeDescriptor<T>::type_ptr = &TypeDescriptor<T>::type;
  if (TypeDescriptor<T>::Dtype() < 0) {
    return false;
  }

  Safe_PyObjectPtr typeDict_obj =
      make_safe(PyObject_GetAttrString(numpy, "sctypeDict"));
  if (!typeDict_obj) return false;
  // Add the type object to `numpy.typeDict`: that makes
  // `numpy.dtype(type_name)` work.
  if (PyDict_SetItemString(
          typeDict_obj.get(), TypeDescriptor<T>::kTypeName,
          reinterpret_cast<PyObject*>(&TypeDescriptor<T>::type)) < 0) {
    return false;
  }

  // Support dtype(type_name)
  if (PyDict_SetItemString(TypeDescriptor<T>::type.tp_dict, "dtype",
                           reinterpret_cast<PyObject*>(
                               &CustomFloatTypeDescriptor<T>::npy_descr)) < 0) {
    return false;
  }

  return RegisterCasts<T>() && ufuncs::RegisterUFuncs<T>(numpy);
}

}  // namespace custom_float_internal
}  // namespace tensorflow

#endif  // TENSORFLOW_PYTHON_LIB_CORE_CUSTOM_FLOAT_H_


text:
DUMP6FILE=/user/worker/hbase-dump-6-months-18feb/webpage

echo "Submitting the job to the Memex cluster."
time spark-submit \
    --master 'yarn-client' \
    --num-executors 50 \
    ${DIG_CRF_HOME}/src/count/countGoodJson.py \
    -- \
    --input ${DUMP6FILE}

redpajama_set_name: RedPajamaGithub


text:
<?php

define('DEBUG', false);
define('GH_API_URL', 'https://api.github.com');

date_default_timezone_set('America/Los_Angeles');

function main(){

    //Parse the config file
    $configFile = getcwd() . "/.gh-backup";
    if(!file_exists($configFile)){
        $configFile = getenv("HOME") . "/.gh-backup";
        if(!file_exists($configFile)){
            echoErr("Couldn't locate a github backup configuration file");
            exit(1);
        }
    }
    $configData = parseConfig($configFile);

    //Build up a list of repos to backup
    $credentials = array(
        $configData['username'],
        $configData['token']
    );
    $repoList = array();
    $repoList = array_merge(
        $repoList,
        myRepoList($credentials),
        orgsRepoList($credentials)
    );
    if(isset($configData['filter'])){
        $filter = $configData['filter'];
        foreach($repoList as $index => $repo){
            if(preg_match($filter, $repo) == 0){
                unset($repoList[$index]);
            }
        }
    }
    $repoList = array_unique($repoList);
    $repoList = array_values($repoList); # Re-index

    $instanceBackupDir = $configData['directory'] . "/" . date('Y-m-d');
    exec("mkdir -p {$instanceBackupDir}");
    chdir($instanceBackupDir);
    foreach($repoList as $repoUrl){
        preg_match('/:(.*)\//', $repoUrl, $matches);
        $entity = $matches[1]; # User or Org
        exec("mkdir -p {$entity}");
        chdir($entity);
        exec("git clone --mirror {$repoUrl}");
        chdir("../");
    }
}

function orgsRepoList($credentials){

    $repoUrlList = array();

    $orgGenerator = apiAllResults($credentials, '/user/memberships/orgs');
    foreach($orgGenerator as $orgMembership){
        $orgRepoUrl = implode('/', array(
            '/orgs',
            $orgMembership['organization']['login'],
            'repos'
        ));
        $repoGenerator = apiAllResults($credentials, $orgRepoUrl);
        foreach($repoGenerator as $repo){
            $repoUrlList[] = $repo['ssh_url'];
        }
    }

    return $repoUrlList;
}

function myRepoList($credentials){

    $repoUrlList = array();
    $nextPage = false;

    $generator = apiAllResults($credentials, '/user/repos');
    foreach($generator as $repo){
        $repoUrlList[] = $repo['ssh_url'];
    }

    return $repoUrlList;
}

function apiAllResults($credentials, $relativePath, $method='GET', $data=false){

    $nextPage = $relativePath;

    do {

        list($response, $headers) = apiRequest($credentials, $nextPage, $method, $data);
        foreach($response as $result)
            yield $result;

        $nextPage = false;
        if(isset($headers['Link']) && !empty($headers['Link'])){
            $links = explode(',', $headers['Link']);
            foreach($links as $linkData){
                list($link, $rel) = array_map('trim', explode(';', $linkData, 2));
                if($rel == 'rel="next"'){
                    $nextPage = trim($link, ' <>');
                }
            }
        }

    } while($nextPage !== false);

}

function apiRequest($credentials, $url, $method='GET', $data=false){

    if(preg_match('/^http(s)?:\/\//', $url) == 0)
        $url = GH_API_URL . $url;

    $headers = array(
        'User-Agent: github-backup',
        'Content-Type: application/json',
        'Authorization: Basic ' . base64_encode($credentials[0] . ":" . $credentials[1])
    );
    if($data !== false){
        $data = json_encode($data);
    }

    list($response, $code, $headers) = curlRequest($url, $method, $data, $headers);
    if($code > 300)
        throw new Exception($response);

    return array(
        json_decode($response, true),
        $headers
    );
}

function curlRequest($url, $method='GET', $data=false, $requestHeaders=array()){

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    if($data !== false)
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    if(DEBUG)
        curl_setopt($ch, CURLOPT_VERBOSE, true);
    $response = curl_exec($ch);
    $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    list($rawResponseHeaders, $responseBody) = explode("\r\n\r\n", $response, 2);
    $rawResponseHeaders = explode("\r\n", $rawResponseHeaders);
    $responseHeaders = array();
    foreach($rawResponseHeaders as $header){
        list($key, $value) = array_map('trim', explode(':', $header, 2));
        $responseHeaders[$key] = $value;
    }
    return array($responseBody, $responseCode, $responseHeaders);
}

function parseConfig($configFile){

    $configData = json_decode(file_get_contents($configFile), true);
    if($configData == null){
        echoErr("Couldn't parse configuration file");
        exit(1);
    }

    if(!isset($configData['username']) || empty($configData['username'])){
        echoErr("Configuration error - a username is required");
        exit(1);
    }
    if(!isset($configData['token']) || empty($configData['token'])){
        echoErr("Configuration error - a token is required");
        exit(1);
    }

    if(!isset($configData['directory']) || empty($configData['directory'])){
        echoErr("Configuration error - a backup directory must be specified");
        exit(1);
    }
    if(strpos($configData['directory'],'/') != 0){
        $configData['directory'] = getcwd() . '/' . $configData['directory'];
    }

    return $configData;
}

function echoErr($msg){

    file_put_contents('php://stderr', $msg . "\n");
}

main();


text:
"""
    Setup file for tsfresh.

    This file was generated with PyScaffold 2.5.6, a tool that easily
    puts up a scaffold for your new Python project. Learn more under:
    http://pyscaffold.readthedocs.org/
"""

import sys

from setuptools import find_packages, setup

with open("README.md") as f:
    long_description = f.read()

with open("requirements.txt") as f:
    requirements = [line for line in f if not line.startswith("#")]

needs_sphinx = {"build_sphinx", "upload_docs"}.intersection(sys.argv)
sphinx = ["sphinx", "sphinx_rtd_theme"] if needs_sphinx else []

setup(
    use_scm_version=True,
    long_description=long_description,
    long_description_content_type="text/markdown",
    setup_requires=["setuptools_scm"] + sphinx,
    packages=find_packages(exclude=["tests.*", "tests"]),
    install_requires=requirements,
)


text:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Days : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DayPilotCalendar1.DataSource = getData();
            DataBind();
        }

    }
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        int days = Convert.ToInt32(DropDownList1.SelectedValue);
        DayPilotCalendar1.Days = days;
    }

    protected DataTable getData()
    {
        DataTable dt;
        dt = new DataTable();
        dt.Columns.Add("start", typeof(DateTime));
        dt.Columns.Add("end", typeof(DateTime));
        dt.Columns.Add("name", typeof(string));
        dt.Columns.Add("id", typeof(string));

        DataRow dr;

        dr = dt.NewRow();
        dr["id"] = 0;
        dr["start"] = Convert.ToDateTime("15:50");
        dr["end"] = Convert.ToDateTime("15:55");
        dr["name"] = "Event 1";
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["id"] = 1;
        dr["start"] = Convert.ToDateTime("16:00");
        dr["end"] = Convert.ToDateTime("17:00");
        dr["name"] = "Event 2";
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["id"] = 2;
        dr["start"] = Convert.ToDateTime("16:15");
        dr["end"] = Convert.ToDateTime("18:45");
        dr["name"] = "Event 3";
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["id"] = 3;
        dr["start"] = Convert.ToDateTime("16:30");
        dr["end"] = Convert.ToDateTime("17:30");
        dr["name"] = "Sales Dept. Meeting Once Again";
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["id"] = 4;
        dr["start"] = Convert.ToDateTime("8:00");
        dr["end"] = Convert.ToDateTime("9:00");
        dr["name"] = "Event 4";
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["id"] = 5;
        dr["start"] = Convert.ToDateTime("22:00");
        dr["end"] = Convert.ToDateTime("6:00").AddDays(1);
        dr["name"] = "Event 5";
        dt.Rows.Add(dr);

        dr = dt.NewRow();
        dr["id"] = 6;
        dr["start"] = Convert.ToDateTime("11:00");
        dr["end"] = Convert.ToDateTime("13:00");
        dr["name"] = "Event 6";
        dt.Rows.Add(dr);

        return dt;

    }

}


text:
import { useEffect, useReducer, useRef } from "react";

// Source: https://usehooks-ts.com/react-hook/use-fetch

interface State<T> {
  data?: T;
  error?: Error;
}

type Cache<T> = { [url: string]: T };

// discriminated union type
type Action<T> =
  | { type: "loading" }
  | { type: "fetched"; payload: T }
  | { type: "error"; payload: Error };

function useFetch<T = unknown>(url?: string, options?: RequestInit): State<T> {
  const cache = useRef<Cache<T>>({});

  // Used to prevent state update if the component is unmounted
  const cancelRequest = useRef<boolean>(false);

  const initialState: State<T> = {
    error: undefined,
    data: undefined,
  };

  // Keep state logic separated
  const fetchReducer = (state: State<T>, action: Action<T>): State<T> => {
    switch (action.type) {
      case "loading":
        return { ...initialState };
      case "fetched":
        return { ...initialState, data: action.payload };
      case "error":
        return { ...initialState, error: action.payload };
      default:
        return state;
    }
  };

  const [state, dispatch] = useReducer(fetchReducer, initialState);

  useEffect(() => {
    // Do nothing if the url is not given
    if (!url) return;

    cancelRequest.current = false;

    const fetchData = async () => {
      dispatch({ type: "loading" });

      // If a cache exists for this url, return it
      if (cache.current[url]) {
        dispatch({ type: "fetched", payload: cache.current[url] });
        return;
      }

      try {
        const response = await fetch(url, options);
        if (!response.ok) {
          throw new Error(response.statusText);
        }

        const data = await response.json();

        // catch API errors
        if (
          response.headers.has("MediaWiki-API-Error") ||
          (data && data.errors)
        ) {
          throw new Error(data.errors[0]["*"] || "Unknown MediaWiki-API-Error");
        }

        cache.current[url] = data;
        if (cancelRequest.current) return;

        dispatch({ type: "fetched", payload: data });
      } catch (error) {
        if (cancelRequest.current) return;

        dispatch({ type: "error", payload: error as Error });
      }
    };

    void fetchData();

    // Use the cleanup function for avoiding a possibly...
    // ...state update after the component was unmounted
    return () => {
      cancelRequest.current = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [url]);

  return state;
}

export { useFetch };


text:
package com.java.leetCode;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by mi on 17-8-3.
 */
public class LetterCombinations_17 {
    public static List<String> letterCombinations1(String digits) {
        int len = digits.length();
        List<String> res = new ArrayList<String>();
        String[] map = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        if (len <= 0) {
            return res;
        }
        res.add("");
        for(int i = 0;i<len;i++) {
            int x = Character.getNumericValue(digits.charAt(i));
            while (res.get(0).length() == i) {
                String t = res.remove(0);
                for (char s : map[x].toCharArray()) {
                    res.add(t + s);
                }
            }
        }
        return res;
    }
    public static List<String> letterCombinations(String digits) {
        LinkedList<String> ans = new LinkedList<String>();
        String[] mapping = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
        ans.add("");
        for(int i =0; i<digits.length();i++){
            int x = Character.getNumericValue(digits.charAt(i));
            while(ans.peek().length()==i){
                String t = ans.remove();
                for(char s : mapping[x].toCharArray())
                    ans.add(t+s);
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        System.out.print(letterCombinations1("2"));
    }
}


text:
module Chronic
  module Handlers
    module_function

    # Handle month/day
    def handle_m_d(month, day, time_tokens, options)
      month.start = self.now
      span = month.this(options[:context])
      year, month = span.begin.year, span.begin.month
      day_start = Chronic.time_class.local(year, month, day)

      day_or_time(day_start, time_tokens, options)
    end

    # Handle repeater-month-name/scalar-day
    def handle_rmn_sd(tokens, options)
      month = tokens[0].get_tag(RepeaterMonthName)
      day = tokens[1].get_tag(ScalarDay).type

      return if month_overflow?(self.now.year, month.index, day)

      handle_m_d(month, day, tokens[2..tokens.size], options)
    end

    # Handle repeater-month-name/scalar-day with separator-on
    def handle_rmn_sd_on(tokens, options)
      if tokens.size > 3
        month = tokens[2].get_tag(RepeaterMonthName)
        day = tokens[3].get_tag(ScalarDay).type
        token_range = 0..1
      else
        month = tokens[1].get_tag(RepeaterMonthName)
        day = tokens[2].get_tag(ScalarDay).type
        token_range = 0..0
      end

      return if month_overflow?(self.now.year, month.index, day)

      handle_m_d(month, day, tokens[token_range], options)
    end

    # Handle repeater-month-name/ordinal-day
    def handle_rmn_od(tokens, options)
      month = tokens[0].get_tag(RepeaterMonthName)
      day = tokens[1].get_tag(OrdinalDay).type

      return if month_overflow?(self.now.year, month.index, day)

      handle_m_d(month, day, tokens[2..tokens.size], options)
    end

    # Handle ordinal this month
    def handle_od_rm(tokens, options)
      day = tokens[0].get_tag(OrdinalDay).type
      month = tokens[2].get_tag(RepeaterMonth)
      handle_m_d(month, day, tokens[3..tokens.size], options)
    end

    # Handle ordinal-day/repeater-month-name
    def handle_od_rmn(tokens, options)
      month = tokens[1].get_tag(RepeaterMonthName)
      day = tokens[0].get_tag(OrdinalDay).type

      return if month_overflow?(self.now.year, month.index, day)

      handle_m_d(month, day, tokens[2..tokens.size], options)
    end

    def handle_sy_rmn_od(tokens, options)
      year = tokens[0].get_tag(ScalarYear).type
      month = tokens[1].get_tag(RepeaterMonthName).index
      day = tokens[2].get_tag(OrdinalDay).type
      time_tokens = tokens.last(tokens.size - 3)

      return if month_overflow?(year, month, day)

      begin
        day_start = Chronic.time_class.local(year, month, day)
        day_or_time(day_start, time_tokens, options)
      rescue ArgumentError
        nil
      end
    end

    # Handle scalar-day/repeater-month-name
    def handle_sd_rmn(tokens, options)
      month = tokens[1].get_tag(RepeaterMonthName)
      day = tokens[0].get_tag(ScalarDay).type

      return if month_overflow?(self.now.year, month.index, day)

      handle_m_d(month, day, tokens[2..tokens.size], options)
    end

    # Handle repeater-month-name/ordinal-day with separator-on
    def handle_rmn_od_on(tokens, options)
      if tokens.size > 3
        month = tokens[2].get_tag(RepeaterMonthName)
        day = tokens[3].get_tag(OrdinalDay).type
        token_range = 0..1
      else
        month = tokens[1].get_tag(RepeaterMonthName)
        day = tokens[2].get_tag(OrdinalDay).type
        token_range = 0..0
      end

      return if month_overflow?(self.now.year, month.index, day)

      handle_m_d(month, day, tokens[token_range], options)
    end

    # Handle repeater-month-name/scalar-year
    def handle_rmn_sy(tokens, options)
      month = tokens[0].get_tag(RepeaterMonthName).index
      year = tokens[1].get_tag(ScalarYear).type

      if month == 12
        next_month_year = year + 1
        next_month_month = 1
      else
        next_month_year = year
        next_month_month = month + 1
      end

      begin
        end_time = Chronic.time_class.local(next_month_year, next_month_month)
        Span.new(Chronic.time_class.local(year, month), end_time)
      rescue ArgumentError
        nil
      end
    end

    # Handle generic timestamp (ruby 1.8)
    def handle_generic(tokens, options)
      t = Chronic.time_class.parse(options[:text])
      Span.new(t, t + 1)
    end

    # Handle repeater-month-name/scalar-day/scalar-year
    def handle_rmn_sd_sy(tokens, options)
      month = tokens[0].get_tag(RepeaterMonthName).index
      day = tokens[1].get_tag(ScalarDay).type
      year = tokens[2].get_tag(ScalarYear).type
      time_tokens = tokens.last(tokens.size - 3)

      return if month_overflow?(year, month, day)

      begin
        day_start = Chronic.time_class.local(year, month, day)
        day_or_time(day_start, time_tokens, options)
      rescue ArgumentError
        nil
      end
    end

    # Handle repeater-month-name/ordinal-day/scalar-year
    def handle_rmn_od_sy(tokens, options)
      month = tokens[0].get_tag(RepeaterMonthName).index
      day = tokens[1].get_tag(OrdinalDay).type
      year = tokens[2].get_tag(ScalarYear).type
      time_tokens = tokens.last(tokens.size - 3)

      return if month_overflow?(year, month, day)

      begin
        day_start = Chronic.time_class.local(year, month, day)
        day_or_time(day_start, time_tokens, options)
      rescue ArgumentError
        nil
      end
    end

    # Handle oridinal-day/repeater-month-name/scalar-year
    def handle_od_rmn_sy(tokens, options)
      day = tokens[0].get_tag(OrdinalDay).type
      month = tokens[1].get_tag(RepeaterMonthName).index
      year = tokens[2].get_tag(ScalarYear).type
      time_tokens = tokens.last(tokens.size - 3)

      return if month_overflow?(year, month, day)

      begin
        day_start = Chronic.time_class.local(year, month, day)
        day_or_time(day_start, time_tokens, options)
      rescue ArgumentError
        nil
      end
    end

    # Handle scalar-day/repeater-month-name/scalar-year
    def handle_sd_rmn_sy(tokens, options)
      new_tokens = [tokens[1], tokens[0], tokens[2]]
      time_tokens = tokens.last(tokens.size - 3)
      handle_rmn_sd_sy(new_tokens + time_tokens, options)
    end

    # Handle scalar-month/scalar-day/scalar-year (endian middle)
    def handle_sm_sd_sy(tokens, options)
      month = tokens[0].get_tag(ScalarMonth).type
      day = tokens[1].get_tag(ScalarDay).type
      year = tokens[2].get_tag(ScalarYear).type
      time_tokens = tokens.last(tokens.size - 3)

      return if month_overflow?(year, month, day)

      begin
        day_start = Chronic.time_class.local(year, month, day)
        day_or_time(day_start, time_tokens, options)
      rescue ArgumentError
        nil
      end
    end

    # Handle scalar-day/scalar-month/scalar-year (endian little)
    def handle_sd_sm_sy(tokens, options)
      new_tokens = [tokens[1], tokens[0], tokens[2]]
      time_tokens = tokens.last(tokens.size - 3)
      handle_sm_sd_sy(new_tokens + time_tokens, options)
    end

    # Handle scalar-year/scalar-month/scalar-day
    def handle_sy_sm_sd(tokens, options)
      new_tokens = [tokens[1], tokens[2], tokens[0]]
      time_tokens = tokens.last(tokens.size - 3)
      handle_sm_sd_sy(new_tokens + time_tokens, options)
    end

    # Handle scalar-month/scalar-day
    def handle_sm_sd(tokens, options)
      month = tokens[0].get_tag(ScalarMonth).type
      day = tokens[1].get_tag(ScalarDay).type
      year = self.now.year
      time_tokens = tokens.last(tokens.size - 2)

      return if month_overflow?(year, month, day)

      begin
        day_start = Chronic.time_class.local(year, month, day)
        day_start = Chronic.time_class.local(year + 1, month, day) if options[:context] == :future && day_start < now
        day_or_time(day_start, time_tokens, options)
      rescue ArgumentError
        nil
      end
    end

    # Handle scalar-day/scalar-month
    def handle_sd_sm(tokens, options)
      new_tokens = [tokens[1], tokens[0]]
      time_tokens = tokens.last(tokens.size - 2)
      handle_sm_sd(new_tokens + time_tokens, options)
    end

    def handle_year_and_month(year, month)
      if month == 12
        next_month_year = year + 1
        next_month_month = 1
      else
        next_month_year = year
        next_month_month = month + 1
      end

      begin
        end_time = Chronic.time_class.local(next_month_year, next_month_month)
        Span.new(Chronic.time_class.local(year, month), end_time)
      rescue ArgumentError
        nil
      end
    end

    # Handle scalar-month/scalar-year
    def handle_sm_sy(tokens, options)
      month = tokens[0].get_tag(ScalarMonth).type
      year = tokens[1].get_tag(ScalarYear).type
      handle_year_and_month(year, month)
    end

    # Handle scalar-year/scalar-month
    def handle_sy_sm(tokens, options)
      year = tokens[0].get_tag(ScalarYear).type
      month = tokens[1].get_tag(ScalarMonth).type
      handle_year_and_month(year, month)
    end

    # Handle RepeaterDayName RepeaterMonthName OrdinalDay
    def handle_rdn_rmn_od(tokens, options)
      month = tokens[1].get_tag(RepeaterMonthName)
      day = tokens[2].get_tag(OrdinalDay).type
      time_tokens = tokens.last(tokens.size - 3)
      year = self.now.year

      return if month_overflow?(year, month.index, day)

      begin
        if time_tokens.empty?
          start_time = Chronic.time_class.local(year, month.index, day)
          end_time = time_with_rollover(year, month.index, day + 1)
          Span.new(start_time, end_time)
        else
          day_start = Chronic.time_class.local(year, month.index, day)
          day_or_time(day_start, time_tokens, options)
        end
      rescue ArgumentError
        nil
      end
    end

    # Handle RepeaterDayName OrdinalDay
    def handle_rdn_od(tokens, options)
      day = tokens[1].get_tag(OrdinalDay).type
      time_tokens = tokens.last(tokens.size - 2)
      year = self.now.year
      month = self.now.month
      if options[:context] == :future
        self.now.day > day ? month += 1 : month
      end

      return if month_overflow?(year, month, day)

      begin
        if time_tokens.empty?
          start_time = Chronic.time_class.local(year, month, day)
          end_time = time_with_rollover(year, month, day + 1)
          Span.new(start_time, end_time)
        else
          day_start = Chronic.time_class.local(year, month, day)
          day_or_time(day_start, time_tokens, options)
        end
      rescue ArgumentError
        nil
      end
    end

    # Handle RepeaterDayName RepeaterMonthName ScalarDay
    def handle_rdn_rmn_sd(tokens, options)
      month = tokens[1].get_tag(RepeaterMonthName)
      day = tokens[2].get_tag(ScalarDay).type
      time_tokens = tokens.last(tokens.size - 3)
      year = self.now.year

      return if month_overflow?(year, month.index, day)

      begin
        if time_tokens.empty?
          start_time = Chronic.time_class.local(year, month.index, day)
          end_time = time_with_rollover(year, month.index, day + 1)
          Span.new(start_time, end_time)
        else
          day_start = Chronic.time_class.local(year, month.index, day)
          day_or_time(day_start, time_tokens, options)
        end
      rescue ArgumentError
        nil
      end
    end

    # Handle RepeaterDayName RepeaterMonthName ScalarDay ScalarYear
    def handle_rdn_rmn_sd_sy(tokens, options)
      month = tokens[1].get_tag(RepeaterMonthName)
      day = tokens[2].get_tag(ScalarDay).type
      year = tokens[3].get_tag(ScalarYear).type

      return if month_overflow?(year, month.index, day)

      begin
        start_time = Chronic.time_class.local(year, month.index, day)
        end_time = time_with_rollover(year, month.index, day + 1)
        Span.new(start_time, end_time)
      rescue ArgumentError
        nil
      end
    end

    def handle_sm_rmn_sy(tokens, options)
      day = tokens[0].get_tag(ScalarDay).type
      month = tokens[1].get_tag(RepeaterMonthName).index
      year = tokens[2].get_tag(ScalarYear).type
      if tokens.size > 3
        time = get_anchor([tokens.last], options).begin
        h, m, s = time.hour, time.min, time.sec
        time = Chronic.time_class.local(year, month, day, h, m, s)
        end_time = Chronic.time_class.local(year, month, day + 1, h, m, s)
      else
        time = Chronic.time_class.local(year, month, day)
        day += 1 unless day >= 31
        end_time = Chronic.time_class.local(year, month, day)
      end
      Span.new(time, end_time)
    end

    # anchors

    # Handle repeaters
    def handle_r(tokens, options)
      dd_tokens = dealias_and_disambiguate_times(tokens, options)
      get_anchor(dd_tokens, options)
    end

    # Handle repeater/grabber/repeater
    def handle_r_g_r(tokens, options)
      new_tokens = [tokens[1], tokens[0], tokens[2]]
      handle_r(new_tokens, options)
    end

    # arrows

    # Handle scalar/repeater/pointer helper
    def handle_srp(tokens, span, options)
      distance = tokens[0].get_tag(Scalar).type
      repeater = tokens[1].get_tag(Repeater)
      pointer = tokens[2].get_tag(Pointer).type

      repeater.offset(span, distance, pointer) if repeater.respond_to?(:offset)
    end

    # Handle scalar/repeater/pointer
    def handle_s_r_p(tokens, options)
      span = Span.new(self.now, self.now + 1)

      handle_srp(tokens, span, options)
    end

    # Handle pointer/scalar/repeater
    def handle_p_s_r(tokens, options)
      new_tokens = [tokens[1], tokens[2], tokens[0]]
      handle_s_r_p(new_tokens, options)
    end

    # Handle scalar/repeater/pointer/anchor
    def handle_s_r_p_a(tokens, options)
      anchor_span = get_anchor(tokens[3..tokens.size - 1], options)
      handle_srp(tokens, anchor_span, options)
    end

    def handle_s_r_a_s_r_p_a(tokens, options)
      anchor_span = get_anchor(tokens[4..tokens.size - 1], options)

      span = handle_srp(tokens[0..1]+tokens[4..6], anchor_span, options)
      handle_srp(tokens[2..3]+tokens[4..6], span, options)
    end

    # narrows

    # Handle oridinal repeaters
    def handle_orr(tokens, outer_span, options)
      repeater = tokens[1].get_tag(Repeater)
      repeater.start = outer_span.begin - 1
      ordinal = tokens[0].get_tag(Ordinal).type
      span = nil

      ordinal.times do
        span = repeater.next(:future)

        if span.begin >= outer_span.end
          span = nil
          break
        end
      end

      span
    end

    # Handle ordinal/repeater/separator/repeater
    def handle_o_r_s_r(tokens, options)
      outer_span = get_anchor([tokens[3]], options)
      handle_orr(tokens[0..1], outer_span, options)
    end

    # Handle ordinal/repeater/grabber/repeater
    def handle_o_r_g_r(tokens, options)
      outer_span = get_anchor(tokens[2..3], options)
      handle_orr(tokens[0..1], outer_span, options)
    end

    # support methods

    def day_or_time(day_start, time_tokens, options)
      outer_span = Span.new(day_start, day_start + (24 * 60 * 60))

      if !time_tokens.empty?
        self.now = outer_span.begin
        get_anchor(dealias_and_disambiguate_times(time_tokens, options), options)
      else
        outer_span
      end
    end

    def get_anchor(tokens, options)
      grabber = Grabber.new(:this)
      pointer = :future
      repeaters = get_repeaters(tokens)
      repeaters.size.times { tokens.pop }

      if tokens.first && tokens.first.get_tag(Grabber)
        grabber = tokens.shift.get_tag(Grabber)
      end

      head = repeaters.shift
      head.start = self.now

      case grabber.type
      when :last
        outer_span = head.next(:past)
      when :this
        if options[:context] != :past and repeaters.size > 0
          outer_span = head.this(:none)
        else
          outer_span = head.this(options[:context])
        end
      when :next
        outer_span = head.next(:future)
      else
        raise "Invalid grabber"
      end

      if Chronic.debug
        puts "Handler-class: #{head.class}"
        puts "--#{outer_span}"
      end

      find_within(repeaters, outer_span, pointer)
    end

    def get_repeaters(tokens)
      tokens.map { |token| token.get_tag(Repeater) }.compact.sort.reverse
    end

    def month_overflow?(year, month, day)
      if Date.leap?(year)
        day > RepeaterMonth::MONTH_DAYS_LEAP[month - 1]
      else
        day > RepeaterMonth::MONTH_DAYS[month - 1]
      end
    rescue ArgumentError
      false
    end

    # Recursively finds repeaters within other repeaters.
    # Returns a Span representing the innermost time span
    # or nil if no repeater union could be found
    def find_within(tags, span, pointer)
      puts "--#{span}" if Chronic.debug
      return span if tags.empty?

      head = tags.shift
      head.start = (pointer == :future ? span.begin : span.end)
      h = head.this(:none)

      if span.cover?(h.begin) || span.cover?(h.end)
        find_within(tags, h, pointer)
      end
    end

    def time_with_rollover(year, month, day)
      date_parts =
        if month_overflow?(year, month, day)
          if month == 12
            [year + 1, 1, 1]
          else
            [year, month + 1, 1]
          end
        else
          [year, month, day]
        end
      Chronic.time_class.local(*date_parts)
    end

    def dealias_and_disambiguate_times(tokens, options)
      # handle aliases of am/pm
      # 5:00 in the morning -> 5:00 am
      # 7:00 in the evening -> 7:00 pm

      day_portion_index = nil
      tokens.each_with_index do |t, i|
        if t.get_tag(RepeaterDayPortion)
          day_portion_index = i
          break
        end
      end

      time_index = nil
      tokens.each_with_index do |t, i|
        if t.get_tag(RepeaterTime)
          time_index = i
          break
        end
      end

      if day_portion_index && time_index
        t1 = tokens[day_portion_index]
        t1tag = t1.get_tag(RepeaterDayPortion)

        case t1tag.type
        when :morning
          puts '--morning->am' if Chronic.debug
          t1.untag(RepeaterDayPortion)
          t1.tag(RepeaterDayPortion.new(:am))
        when :afternoon, :evening, :night
          puts "--#{t1tag.type}->pm" if Chronic.debug
          t1.untag(RepeaterDayPortion)
          t1.tag(RepeaterDayPortion.new(:pm))
        end
      end

      # handle ambiguous times if :ambiguous_time_range is specified
      if options[:ambiguous_time_range] != :none
        ambiguous_tokens = []

        tokens.each_with_index do |token, i|
          ambiguous_tokens << token
          next_token = tokens[i + 1]

          if token.get_tag(RepeaterTime) && token.get_tag(RepeaterTime).type.ambiguous? && (!next_token || !next_token.get_tag(RepeaterDayPortion))
            distoken = Token.new('disambiguator')

            distoken.tag(RepeaterDayPortion.new(options[:ambiguous_time_range]))
            ambiguous_tokens << distoken
          end
        end

        tokens = ambiguous_tokens
      end

      tokens
    end

  end

end


text:
package net.cloudkit.enterprises.ocr;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author hongquanli <hongquanli@qq.com>
 * @version 1.0 2016/4/5 20:53
 */
public class OCRTest {

//    public static BufferedImage rotateImage(BufferedImage image, int degree, Color backgroundColor) throws IOException {
//
//        // 原始图象的宽度
//        int iw = image.getWidth();
//        // 原始图象的高度
//        int ih = image.getHeight();
//        int w = 0;
//        int h = 0;
//        int x = 0;
//        int y = 0;
//        degree = degree % 360;
//        if (degree < 0)
//            // 将角度转换到0-360度之间
//            degree = 360 + degree;
//        // 将角度转为弧度
//        double ang = Math.toRadians(degree);
//
//        /**
//         *确定旋转后的图象的高度和宽度
//         */
//        if (degree == 180 || degree == 0 || degree == 360) {
//            w = iw;
//            h = ih;
//        } else if (degree == 90 || degree == 270) {
//            w = ih;
//            h = iw;
//        } else {
//            int d = iw + ih;
//            w = (int) (d * Math.abs(Math.cos(ang)));
//            h = (int) (d * Math.abs(Math.sin(ang)));
//        }
//
//        // 确定原点坐标
//        x = (w / 2) - (iw / 2);
//        y = (h / 2) - (ih / 2);
//        BufferedImage rotatedImage = new BufferedImage(w, h, image.getType());
//        Graphics2D gs = (Graphics2D) rotatedImage.getGraphics();
//        if (backgroundColor == null) {
//            rotatedImage = gs.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);
//        } else {
//            gs.setColor(backgroundColor);
//            // 以给定颜色绘制旋转后图片的背景
//            gs.fillRect(0, 0, w, h);
//        }
//
//        AffineTransform at = new AffineTransform();
//        // 旋转图象
//        at.rotate(ang, w / 2, h / 2);
//        at.translate(x, y);
//        AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
//        op.filter(image, rotatedImage);
//        image = rotatedImage;
//
//        // ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
//        // ImageOutputStream iamgeOut = ImageIO.createImageOutputStream(byteOut);
//
//        // ImageIO.write(image, "png", iamgeOut);
//        // InputStream inputStream = new ByteArrayInputStream(byteOut.toByteArray());
//
//        return image;
//    }

    public static void main(String[] agrs) throws IOException {

        int width = 25;
        int height = 25;
        int fontSize = 20;

        for(int num = 0; num < 10; num ++) {

            // 创建内存图像
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            // 获取图形上下文
            Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
            // 画背景图
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, width, height);
            // 设定字体
            Font font = new Font("Microsoft YaHei UI", Font.PLAIN, fontSize);
            graphics.setFont(font);
            // graphics.setColor(Color.BLACK);

            // 设置字体在图片中的位置 在这里是居中
            FontRenderContext context = graphics.getFontRenderContext();
            Rectangle2D bounds = font.getStringBounds(String.valueOf(num), context);
            double x = (width - bounds.getWidth()) / 2;
            double y = (height - bounds.getHeight()) / 2;
            System.out.println("x:" + x + ", y:" + y + " " + bounds.getWidth() + "-" + bounds.getHeight());

            // graphics.setPaint(new Color(10, 0, 149));
            graphics.setPaint(Color.BLACK);
            // 将验证码字符显示到图象中
            graphics.drawString(String.valueOf(num), (int) x, (int) bounds.getHeight() - 2);
            graphics.dispose();

            for (int i = -60; i <= 60; i++) {

                // image = rotateImage(bufferedImage, i, Color.WHITE);

                BufferedImage rotatedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D gs = (Graphics2D) rotatedImage.getGraphics();
                gs.setColor(Color.WHITE);
                // 以给定颜色绘制旋转后图片的背景
                gs.fillRect(0, 0, width, height);

                AffineTransform at = new AffineTransform();
                int degree = i % 360;
                if (degree < 0)
                    // 将角度转换到0-360度之间
                    degree = 360 + degree;
                // 将角度转为弧度
                double ang = Math.toRadians(degree);
                // 旋转图象
                // at.rotate(i * Math.PI / 180);
                at.rotate(ang, width / 2, height / 2);
                // at.translate(x, y);
                AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
                op.filter(bufferedImage, rotatedImage);

                FileOutputStream fos = new FileOutputStream("D:\\test\\" + num + "_" + (i + 60) + ".jpg");
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
                encoder.encode(rotatedImage);
                fos.close();
            }
        }

        /*
        // 平移原点到图形环境的中心
        graphics.translate(width / 2, height / 2);

        // 旋转文本
        for (int i = -60; i < 60; i++) {
            graphics.rotate(i * Math.PI / 180);
            graphics.setPaint(Color.BLACK);
            graphics.drawString(num, 0, 0);
            break;
        }
        graphics.dispose();
        */
    }
}


text:
    // Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//

using System;
using System.Runtime.CompilerServices;

public class BringUpTest
{
    const int Pass = 100;
    const int Fail = -1;

    [MethodImplAttribute(MethodImplOptions.NoInlining)]
    static int Array4(int i) {
        int[] a = {1, 2, 3, 4};
        return a[i];
    }

    static int Main()
    {
        if (Array4(1) != 2) return Fail;
        return Pass;
    }
}


text:
SET NOCOUNT ON;

SELECT resourceid                             MachineID,
       Replace(p.displayname0, CHAR(9), ' ')  [Program Name],
       Replace(p.publisher0, CHAR(9), ' ')    Publisher,
       version0                               [Version],
       CAST(NULL as DATETIME)                 [timestamp]
FROM   dbo.v_gs_add_remove_programs p INNER JOIN dbo.vsms_r_system s ON p.resourceid = s.itemkey
WHERE  s.obsolete0 = 0 AND
       s.decommissioned0 = 0 AND
       p.displayname0 IS NOT NULL AND
       p.displayname0<>''
UNION
SELECT resourceid                             MachineID,
       Replace(p.displayname0, CHAR(9), ' ')  [Program Name],
       Replace(p.publisher0, CHAR(9), ' ')    Publisher,
       version0                               [Version],
       CAST(NULL as DATETIME)                 [timestamp]
FROM   dbo.v_gs_add_remove_programs_64 p INNER JOIN dbo.vsms_r_system s ON p.resourceid = s.itemkey
WHERE  s.obsolete0 = 0 AND
       s.decommissioned0 = 0 AND
       p.displayname0 IS NOT NULL AND
       p.displayname0<>'';