ERL_NIF_TERM _hh_max(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hh_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 1 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx))
    {
        return enif_make_badarg(env);
    }
   
    if (ctx != NULL)
    {
        if (ctx->data->total_count == 0)
        {
            return enif_make_long(env, 0);
        }
        else
        {
            return enif_make_long(env, hdr_max(ctx->data));
        }
    }

    return make_error(env, "bad_hdr_histogram_nif_impl");
}
Exemple #2
0
static ERL_NIF_TERM
_receive_can_messages (ErlNifEnv* env,
                        CAN_handle* handle,
                        unsigned int chunk_size,
                        long timeout)
{
  int length         = 0,
      i              = 0,
      chunks         = 0;
  ERL_NIF_TERM *list, result;
  canmsg_t     buffer[sizeof(canmsg_t) * BUFFER_LIMIT];
  do {
    int status = _wait_for_input(handle, timeout);
    if (status == 0) break;
    if (status == -1)
      {
        result = enif_make_int(env, errno);
        goto end;
      }
    length = read(handle->device, &buffer[chunks], sizeof(canmsg_t) * chunk_size);
    if (length < 0) break;
    chunks += length / sizeof(canmsg_t) ;
  } while (length > 0 && chunks <= BUFFER_LIMIT && chunks < chunk_size);
  if (chunks > 0)
    {
    if (handle->raw)
      {
        void* data = enif_make_new_binary(env, chunks * sizeof(canmsg_t), &result);
        memcpy(data, buffer, chunks * sizeof(canmsg_t));
      }
    else
      {
      list = enif_alloc(sizeof(ERL_NIF_TERM) * chunks);
      // rewrite canmsgs to list of tuples
      for (i = 0; i < chunks; i++)
        {
        canmsg_t* can_msg = buffer + i;
        ERL_NIF_TERM bin;
        void* data = enif_make_new_binary(env, can_msg->length, &bin);
        memcpy(data, can_msg->data, can_msg->length);
        list[i] = enif_make_tuple3(env,
                                   enif_make_int(env, can_msg->id),
                                   enif_make_tuple2(env,
                                                    enif_make_long(env, can_msg->timestamp.tv_sec),
                                                    enif_make_long(env, can_msg->timestamp.tv_usec)),
                                   bin);
        }
      result = enif_make_list_from_array(env, list, chunks);
      enif_free(list);
      }
    }
  else if (length == 0)
    result = enif_make_int(env, 0);
  else
    result = enif_make_int(env, errno);
end:
  return result;
}
Exemple #3
0
static ERL_NIF_TERM make_scalar(ErlNifEnv* env, yaml_event_t *event, int flags)
{
    int as_atom = PLAIN_AS_ATOM & flags;
    long int i;
    double d;
    int type;
    yaml_scalar_style_t style = event->data.scalar.style;
    ERL_NIF_TERM rterm;

    if (as_atom && style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
	rterm =  enif_make_atom_len(env,
				    (char *) event->data.scalar.value,
				    event->data.scalar.length);
    } else if (style == YAML_DOUBLE_QUOTED_SCALAR_STYLE) {
	rterm = make_binary_size(env, event->data.scalar.value,
				 event->data.scalar.length);
    } else if ((type = make_num(env, event->data.scalar.value, 
				event->data.scalar.length, &i, &d))) {
	if (type == INTEGER)
	    rterm = enif_make_long(env, i);
	else
	    rterm = enif_make_double(env, d);
    } else if (as_atom && style == YAML_PLAIN_SCALAR_STYLE && event->data.scalar.length) {
	rterm = enif_make_atom_len(env,
				   (char *) event->data.scalar.value,
				   event->data.scalar.length);
    } else {
	rterm = make_binary_size(env, event->data.scalar.value,
				 event->data.scalar.length);
    }

    return rterm;
}
Exemple #4
0
    static ERL_NIF_TERM
nif_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
    SRLY_STATE *sp = NULL;
    ErlNifBinary buf = {0};
    ssize_t n = -1;

    ERL_NIF_TERM rv = atom_ok;


    if (!enif_get_resource(env, argv[0], SRLY_STATE_RESOURCE, (void **)&sp))
        return enif_make_badarg(env);

    if (!enif_inspect_iolist_as_binary(env, argv[1], (ErlNifBinary *)&buf))
        return enif_make_badarg(env);

    n = write(sp->fd, buf.data, buf.size);

    if (n < 0)
        rv = error_tuple(env, errno);
    else if (n != buf.size)
        rv = enif_make_tuple2(env,
            atom_ok,
            enif_make_long(env, n));

    return rv;
}
ERL_NIF_TERM pteracuda_nifs_buffer_size(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
    PCudaBufferRef *ref;
    if (argc != 1 || !enif_get_resource(env, argv[0], pteracuda_buffer_resource, (void **) &ref)) {
        return enif_make_badarg(env);
    }
    return enif_make_tuple2(env, ATOM_OK, enif_make_long(env, ref->buffer->size()));
}
Exemple #6
0
ERL_NIF_TERM exmagick_get_attr (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
  char atom[EXM_MAX_ATOM_SIZE];
  exm_resource_t *resource;

  EXM_INIT;
  ErlNifResourceType *type = (ErlNifResourceType *) enif_priv_data(env);

  if (0 == enif_get_resource(env, argv[0], type, (void **) &resource))
  { EXM_FAIL(ehandler, "invalid handle"); }

  if (0 == enif_get_atom(env, argv[1], atom, EXM_MAX_ATOM_SIZE, ERL_NIF_LATIN1))
  { EXM_FAIL(ehandler, "invalid attribute"); }

  if (strcmp("adjoin", atom) == 0)
  {
    if (resource->i_info->adjoin == 0)
    { return(enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_atom(env, "false"))); }
    else if (resource->i_info->adjoin == 1)
    { return(enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_atom(env, "true"))); }
  }
  if (strcmp("rows", atom) == 0)
  {
    if (resource->image == NULL)
    { EXM_FAIL(ehandler, "image not loaded"); }

    { return(enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_long(env, resource->image->rows))); }
  }
  if (strcmp("columns", atom) == 0)
  {
    if (resource->image == NULL)
    { EXM_FAIL(ehandler, "image not loaded"); }

    { return(enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_long(env, resource->image->columns))); }
  }
  if (strcmp("density", atom) == 0)
  { return(enif_make_tuple2(env, enif_make_atom(env, "ok"), exmagick_make_utf8str(env, resource->i_info->density))); }
  else if (strcmp("magick", atom) == 0)
  { return(enif_make_tuple2(env, enif_make_atom(env, "ok"), exmagick_make_utf8str(env, resource->image->magick))); }

ehandler:
  return(enif_make_tuple2(env, enif_make_atom(env, "error"), exmagick_make_utf8str(env, errmsg)));
}
Exemple #7
0
static ERL_NIF_TERM get_resource_type(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    PrivData* data = (PrivData*) enif_priv_data(env);
    int ix;
    
    if (!enif_get_int(env, argv[0], &ix) || ix >= 2) {
	return enif_make_badarg(env);
    }
    return enif_make_long(env, data->rt_arr[ix].l);
}
Exemple #8
0
static int test_long(ErlNifEnv* env, long i1)
{
    long i2 = 0;
    ERL_NIF_TERM int_term = enif_make_long(env, i1);
    if (!enif_get_long(env,int_term, &i2) || i1 != i2) {
	fprintf(stderr, "test_long(%ld) ...FAILED i2=%ld\r\n", i1, i2);
	return 0;
    }
    return 1;
}
Exemple #9
0
/* Define an interface for errors. */
ERL_NIF_TERM build_error(ErlNifEnv* env, ERL_NIF_TERM body, 
        const char *pszFile, long lLine) {
    return enif_make_tuple4(env, 
            enif_make_atom(env, "i18n_error"), 
            body,
            enif_make_tuple2(env,
                enif_make_atom(env, "line"),
                enif_make_long(env, lLine)),
            enif_make_tuple2(env,
                enif_make_atom(env, "file"),
                enif_make_atom(env, pszFile)));
}
Exemple #10
0
// convert a python object to an erlang term, return the atom 'unknown' if
// the type can't be converted
static ERL_NIF_TERM pynerl_obj_to_term(ErlNifEnv* env, PyObject* obj) {
	ERL_NIF_TERM term;

	if (obj == Py_False) {
		term = enif_make_atom(env, "false");
	}
	else if (obj == Py_True) {
		term = enif_make_atom(env, "true");
	}
	else if (PyLong_Check(obj)) {
		// TODO: make ints when the size allows to.
		term = enif_make_long(env, PyLong_AsLong(obj));
	}
	else if (PyFloat_Check(obj)) {
		term = enif_make_double(env, PyFloat_AsDouble(obj));
	}
	else if (PyTuple_Check(obj)) {
		Py_ssize_t i, arity = PyTuple_Size(obj);
		ERL_NIF_TERM *terms = (ERL_NIF_TERM*) malloc(sizeof(ERL_NIF_TERM) * (int)arity);

		for (i = 0; i < arity; i++) {
			terms[(int)i] = pynerl_obj_to_term(env, PyTuple_GetItem(obj, i));
		}

		term = enif_make_tuple_from_array(env, terms, (unsigned int)arity);
	}
	else if (PyBytes_Check(obj)) {
		// XXX: the encoding must be latin1
		term = enif_make_string(env, PyBytes_AsString(obj), ERL_NIF_LATIN1);
	}
	else if (PyUnicode_Check(obj)) {
		// XXX: the encoding must be latin1
		term = enif_make_string(env, PyBytes_AsString(PyUnicode_AsLatin1String(obj)), ERL_NIF_LATIN1);
	}
	else if (PyList_Check(obj)) {
		Py_ssize_t i, arity = PyList_Size(obj);
		ERL_NIF_TERM *terms = (ERL_NIF_TERM*) malloc(sizeof(ERL_NIF_TERM) * (int)arity);

		for (i = 0; i < arity; i++) {
			terms[(int)i] = pynerl_obj_to_term(env, PyList_GetItem(obj, i));
		}

		term = enif_make_list_from_array(env, terms, (unsigned int)arity);
	}
	else if (obj == Py_None) {
		term = enif_make_atom(env, "none");
    }
	else {
		term = enif_make_atom(env, "unknown");
    }

	return term;
}
Exemple #11
0
static ERL_NIF_TERM alloc_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary data_bin;
    union { ErlNifResourceType* t; long l;} type;
    union { void* p; long l;} data;
    if (!enif_get_long(env, argv[0], &type.l)
	|| !enif_inspect_binary(env, argv[1], &data_bin)
	|| (data.p = enif_alloc_resource(type.t, data_bin.size))==NULL) {

	return enif_make_badarg(env);
    }
    memcpy(data.p, data_bin.data, data_bin.size);
    return enif_make_long(env, data.l);
}
Exemple #12
0
static ERL_NIF_TERM last_resource_dtor_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ERL_NIF_TERM ret;
    if (resource_dtor_last != NULL) {
	ERL_NIF_TERM bin;	
	memcpy(enif_make_new_binary(env, resource_dtor_last_sz, &bin),
	       resource_dtor_last_data, resource_dtor_last_sz);
	ret = enif_make_tuple3(env,
				enif_make_long(env, (long)resource_dtor_last),
				bin,  
				enif_make_int(env, resource_dtor_cnt));
    }
    else {
	ret = enif_make_list(env,0);
    }
    resource_dtor_last = NULL;
    resource_dtor_last_sz = 0;
    resource_dtor_cnt = 0;
    return ret;
}
ERL_NIF_TERM _hh_count_at(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    long value = 0;
    hh_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 1 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) ||
        !enif_get_int64(env, argv[1], &value))
    {
        return enif_make_badarg(env);
    }
   
    if (ctx != NULL)
    {
        return enif_make_long(env, hdr_count_at_value(ctx->data, value));
    }

    return make_error(env, "bad_hdr_histogram_nif_impl");
}
ERL_NIF_TERM _hh_add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hh_ctx_t* ctx = NULL;
    hh_ctx_t* from = NULL;

    ErlNifResourceType* ctx_type = get_hh_ctx_type(env);
    if (argc != 2 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx) ||
        !enif_get_resource(env, argv[1], ctx_type, (void **)&from))
    {
        return enif_make_badarg(env);
    }
   
    if (ctx != NULL)
    {
        return enif_make_long(env, hdr_add(ctx->data, from->data));
    }

    return make_error(env, "bad_hdr_histogram_nif_impl");
}
Exemple #15
0
static ERL_NIF_TERM make_new_resource_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary data_bin;
    union { struct binary_resource* p; void* vp; long l;} br;
    void* buf;
    ERL_NIF_TERM ret;
    if (!enif_inspect_binary(env, argv[0], &data_bin)
	|| (br.vp = enif_alloc_resource(binary_resource_type,
					sizeof(struct binary_resource)))==NULL
	|| (buf = enif_alloc(data_bin.size)) == NULL) {
	
	return enif_make_badarg(env);
    }    
    memset(br.vp,0xba,sizeof(struct binary_resource)); /* avoid valgrind warning */
    br.p->data = buf;
    br.p->size = data_bin.size;
    memcpy(br.p->data, data_bin.data, data_bin.size);    
    ret = enif_make_resource_binary(env, br.vp, br.p->data, br.p->size);    
    enif_release_resource(br.p);
    return enif_make_tuple2(env, enif_make_long(env,br.l), ret);
}
Exemple #16
0
static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    ErlNifBinary data_bin;
    union { ErlNifResourceType* t; long l; } type;
    union { void* p; long l; } data;

    type.t = NULL;
    if (enif_is_identical(argv[0], atom_binary_resource_type)) {
	type.t = binary_resource_type;
    }
    else {
	enif_get_long(env, argv[0], &type.l);
    }
    if (type.t == NULL 
	|| !enif_get_resource(env, argv[1], type.t, &data.p)) {
	return enif_make_badarg(env);
    }
    enif_alloc_binary(enif_sizeof_resource(data.p), &data_bin);    
    memcpy(data_bin.data, data.p, data_bin.size);
    return enif_make_tuple2(env, enif_make_long(env,data.l),
			    enif_make_binary(env, &data_bin));
}
static int handle_integer(void *ctx, long integerVal)
{
  state_t *st = (state_t *)ctx;
  add_element(st, enif_make_long(st->env, integerVal));
  return 1;
}
Exemple #18
0
static ERL_NIF_TERM make_term_long(struct make_term_info* mti, int n)
{
    long l;
    fill(&l, sizeof(l), n);
    return enif_make_long(mti->dst_env, l);
}
ERL_NIF_TERM _hi_next(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    hi_ctx_t* ctx = NULL;

    ErlNifResourceType* ctx_type = get_hi_ctx_type(env);
    if (argc != 1 ||
        ctx_type == NULL ||
        !enif_get_resource(env, argv[0], ctx_type, (void **)&ctx))
    {
        return enif_make_badarg(env);
    }

    if (ctx != NULL && ctx->type == HDR_ITER_REC)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_recorded_iter_next(ctx->iter)))
        {
            struct hdr_recorded_iter* x = ((struct hdr_recorded_iter*)ctx->iter);
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                int64_t stp = x->count_added_in_this_iteration_step;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_RECORD,
                  enif_make_list(env, 7,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_long(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_long(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_long(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_long(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_long(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_STEP_COUNT,
                          enif_make_long(env,stp))));
            }
        }
    }

    if (ctx != NULL && ctx->type == HDR_ITER_LIN)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_linear_iter_next(ctx->iter)))
        {
            struct hdr_linear_iter* x = ((struct hdr_linear_iter*)ctx->iter);
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                int64_t stp = x->count_added_in_this_iteration_step;
                int32_t vub = x->value_units_per_bucket;
                int64_t nvl = x->next_value_reporting_level;
                int64_t nve = x->next_value_reporting_level_lowest_equivalent;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_LINEAR,
                  enif_make_list(env, 10,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_long(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_long(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_long(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_long(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_long(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_VAL_UNITS_PER_BUCKET,
                          enif_make_int(env,vub)),
                      enif_make_tuple2(env,
                          ATOM_STEP_COUNT,
                          enif_make_long(env,stp)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL,
                          enif_make_long(env,nvl)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL_LOW_EQUIV,
                          enif_make_long(env,nve))));
            }
        }
    }

    if (ctx != NULL && ctx->type == HDR_ITER_LOG)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_log_iter_next(ctx->iter)))
        {
            struct hdr_log_iter* x = (struct hdr_log_iter*)ctx->iter;
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                int64_t stp = x->count_added_in_this_iteration_step;
                int32_t vfb = x->value_units_first_bucket;
                double lgb = x->log_base;
                int64_t nvl = x->next_value_reporting_level;
                int64_t nve = x->next_value_reporting_level_lowest_equivalent;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_LOGARITHMIC,
                  enif_make_list(env, 11,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_long(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_long(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_long(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_long(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_long(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_VAL_UNITS_FIRST_BUCKET,
                          enif_make_int(env,vfb)),
                      enif_make_tuple2(env,
                          ATOM_STEP_COUNT,
                          enif_make_long(env,stp)),
                      enif_make_tuple2(env,
                          ATOM_LOG_BASE,
                          enif_make_double(env,lgb)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL,
                          enif_make_long(env,nvl)),
                      enif_make_tuple2(env,
                          ATOM_NEXT_VAL_REP_LVL_LOW_EQUIV,
                          enif_make_long(env,nve))));
            }
        }
    }

    if (ctx != NULL && ctx->type == HDR_ITER_PCT)
    {
        // skip until first non-zero index
        bool has_next = false;
        while (ctx->iter != NULL && (has_next = hdr_percentile_iter_next(ctx->iter)))
        {
            struct hdr_percentile_iter* x = (struct hdr_percentile_iter*)ctx->iter;
            struct hdr_iter iter = x->iter;
            if (0 != iter.count_at_index)
            {
                bool slv = x->seen_last_value;
                int32_t tph = x->ticks_per_half_distance;
                double pti = x->percentile_to_iterate_to;
                double pct = x->percentile;
                int32_t bdx = iter.bucket_index;
                int64_t sdx = iter.sub_bucket_index;
                int64_t val = iter.value_from_index;
                int64_t cat = iter.count_at_index;
                int64_t cto = iter.count_to_index;
                int64_t heq = iter.highest_equivalent_value;
                return enif_make_tuple2(env,
                  ATOM_PERCENTILE,
                  enif_make_list(env, 10,
                      enif_make_tuple2(env,
                          ATOM_BUCKET_IDX,
                          enif_make_int(env,bdx)),
                      enif_make_tuple2(env,
                          ATOM_SUB_BUCKET_IDX,
                          enif_make_long(env,sdx)),
                      enif_make_tuple2(env,
                          ATOM_VAL_FROM_IDX,
                          enif_make_long(env,val)),
                      enif_make_tuple2(env,
                          ATOM_VAL_AT_IDX,
                          enif_make_long(env,cat)),
                      enif_make_tuple2(env,
                          ATOM_COUNT_AT_IDX,
                          enif_make_long(env,cto)),
                      enif_make_tuple2(env,
                          ATOM_HIGHEST_EQUIV_VAL,
                          enif_make_long(env,heq)),
                      enif_make_tuple2(env,
                          ATOM_SEEN_LAST_VAL,
                          enif_make_atom(env,slv ? "true" : "false")),
                      enif_make_tuple2(env,
                          ATOM_PERCENTILE_TO_ITERATE_TO,
                          enif_make_double(env,pti)),
                      enif_make_tuple2(env,
                          ATOM_PERCENTILE,
                          enif_make_double(env,pct)),
                      enif_make_tuple2(env,
                          ATOM_TICKS_PER_HALF_DISTANCE,
                          enif_make_int(env,tph))));
            }
        }
    }

    return enif_make_tuple2(
        env,
        ATOM_FALSE,
        enif_make_tuple(env,0)
    );
}
ERL_NIF_TERM PCudaFloatBuffer::minmax(ErlNifEnv *env) {
    double minmax[2];
    pcuda_float_minmax(this->data, &minmax[0]);
    return enif_make_tuple2(env, enif_make_long(env, minmax[0]), enif_make_long(env, minmax[1]));
}