///////////////////////////////////////////////////////////////////// // = NMatrix // // A linear algebra library for scientific computation in Ruby. // NMatrix is part of SciRuby. // // NMatrix was originally inspired by and derived from NArray, by // Masahiro Tanaka: http://narray.rubyforge.org // // == Copyright Information // // SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation // NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation // // Please see LICENSE.txt for additional copyright notices. // // == Contributing // // By contributing source code to SciRuby, you agree to be bound by // our Contributor Agreement: // // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement // // == data.cpp // // Functions and data for dealing the data types. /* * Standard Includes */ #include #include /* * Project Includes */ #include "types.h" #include "data.h" /* * Global Variables */ namespace nm { const char* const EWOP_OPS[nm::NUM_EWOPS] = { "+", "-", "*", "/", "**", "%", "==", "!=", "<", ">", "<=", ">=" }; const std::string EWOP_NAMES[nm::NUM_EWOPS] = { "add", "sub", "mul", "div", "pow", "mod", "eqeq", "neq", "lt", "gt", "leq", "geq" }; const std::string NONCOM_EWOP_NAMES[nm::NUM_NONCOM_EWOPS] = { "atan2", "ldexp", "hypot" }; const std::string UNARYOPS[nm::NUM_UNARYOPS] = { "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "exp", "log2", "log10", "sqrt", "erf", "erfc", "cbrt", "gamma", "negate", "floor", "ceil", "round" }; /* * Create a RubyObject from a regular C value (given a dtype). Does not return a VALUE! To get a VALUE, you need to * look at the rval property of what this function returns. */ nm::RubyObject rubyobj_from_cval(void* val, nm::dtype_t dtype) { using namespace nm; switch (dtype) { case BYTE: return RubyObject(*reinterpret_cast(val)); case INT8: return RubyObject(*reinterpret_cast(val)); case INT16: return RubyObject(*reinterpret_cast(val)); case INT32: return RubyObject(*reinterpret_cast(val)); case INT64: return RubyObject(*reinterpret_cast(val)); case FLOAT32: return RubyObject(*reinterpret_cast(val)); case FLOAT64: return RubyObject(*reinterpret_cast(val)); case COMPLEX64: return RubyObject(*reinterpret_cast(val)); case COMPLEX128: return RubyObject(*reinterpret_cast(val)); default: try { throw std::logic_error("Cannot create ruby object"); } catch (std::logic_error err) { printf("%s\n", err.what()); } rb_raise(nm_eDataTypeError, "Conversion to RubyObject requested from unknown/invalid data type (did you try to convert from a VALUE?)"); } return Qnil; } } // end of namespace nm extern "C" { const char* const DTYPE_NAMES[nm::NUM_DTYPES] = { "byte", "int8", "int16", "int32", "int64", "float32", "float64", "complex64", "complex128", "object" }; const size_t DTYPE_SIZES[nm::NUM_DTYPES] = { sizeof(uint8_t), sizeof(int8_t), sizeof(int16_t), sizeof(int32_t), sizeof(int64_t), sizeof(float32_t), sizeof(float64_t), sizeof(nm::Complex64), sizeof(nm::Complex128), sizeof(nm::RubyObject) }; const nm::dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES] = { { nm::BYTE, nm::INT16, nm::INT16, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::INT16, nm::INT8, nm::INT16, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::INT16, nm::INT16, nm::INT16, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::INT32, nm::INT32, nm::INT32, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::INT64, nm::INT64, nm::INT64, nm::INT64, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::COMPLEX128, nm::COMPLEX128, nm::RUBYOBJ}, { nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX128, nm::COMPLEX64, nm::COMPLEX128, nm::RUBYOBJ}, { nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::RUBYOBJ}, { nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ} }; /* * Forward Declarations */ /* * Functions */ /* * Converts a RubyObject */ void rubyval_to_cval(VALUE val, nm::dtype_t dtype, void* loc) { using namespace nm; switch (dtype) { case nm::BYTE: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::INT8: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::INT16: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::INT32: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::INT64: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::FLOAT32: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::FLOAT64: *reinterpret_cast(loc) = static_cast(RubyObject(val)); break; case nm::COMPLEX64: *reinterpret_cast(loc) = RubyObject(val).to(); break; case nm::COMPLEX128: *reinterpret_cast(loc) = RubyObject(val).to(); break; case RUBYOBJ: *reinterpret_cast(loc) = val; //rb_raise(rb_eTypeError, "Attempting a bad conversion from a Ruby value."); break; default: rb_raise(rb_eTypeError, "Attempting a bad conversion."); break; } } /* * Allocate and return a piece of data of the correct dtype, converted from a * given RubyObject. */ void* rubyobj_to_cval(VALUE val, nm::dtype_t dtype) { size_t size = DTYPE_SIZES[dtype]; NM_CONSERVATIVE(nm_register_value(&val)); void* ret_val = NM_ALLOC_N(char, size); rubyval_to_cval(val, dtype, ret_val); NM_CONSERVATIVE(nm_unregister_value(&val)); return ret_val; } void nm_init_data() { volatile VALUE t = INT2FIX(1); volatile nm::RubyObject obj(t); volatile nm::Complex64 a(const_cast(obj)); volatile nm::Complex128 b(const_cast(obj)); } } // end of extern "C" block