/*----------------------------------------------------------------------------- * array_positions : * return an array of positions of a value in an array. * * IS NOT DISTINCT FROM semantics are used for comparisons. Returns NULL when * the input array is NULL. When the value is not found in the array, returns * an empty array. * * This is not strict so we have to test for null inputs explicitly. *----------------------------------------------------------------------------- */ Datum array_positions(PG_FUNCTION_ARGS) { ArrayType *array; Oid collation = PG_GET_COLLATION(); Oid element_type; Datum searched_element, value; bool isnull; int position; TypeCacheEntry *typentry; ArrayMetaState *my_extra; bool null_search; ArrayIterator array_iterator; ArrayBuildState *astate = NULL; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); array = PG_GETARG_ARRAYTYPE_P(0); element_type = ARR_ELEMTYPE(array); position = (ARR_LBOUND(array))[0] - 1; /* * We refuse to search for elements in multi-dimensional arrays, since we * have no good way to report the element's location in the array. */ if (ARR_NDIM(array) > 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("searching for elements in multidimensional arrays is not supported"))); astate = initArrayResult(INT4OID, CurrentMemoryContext, false); if (PG_ARGISNULL(1)) { /* fast return when the array doesn't have nulls */ if (!array_contains_nulls(array)) PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext)); searched_element = (Datum) 0; null_search = true; } else { searched_element = PG_GETARG_DATUM(1); null_search = false; } /* * We arrange to look up type info for array_create_iterator only once per * series of calls, assuming the element type doesn't change underneath * us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO); if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", format_type_be(element_type)))); my_extra->element_type = element_type; fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc, fcinfo->flinfo->fn_mcxt); } /* * Accumulate each array position iff the element matches the given * element. */ array_iterator = array_create_iterator(array, 0, my_extra); while (array_iterate(array_iterator, &value, &isnull)) { position += 1; /* * Can't look at the array element's value if it's null; but if we * search for null, we have a hit. */ if (isnull || null_search) { if (isnull && null_search) astate = accumArrayResult(astate, Int32GetDatum(position), false, INT4OID, CurrentMemoryContext); continue; } /* not nulls, so run the operator */ if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation, searched_element, value))) astate = accumArrayResult(astate, Int32GetDatum(position), false, INT4OID, CurrentMemoryContext); } array_free_iterator(array_iterator); /* Avoid leaking memory when handed toasted input */ PG_FREE_IF_COPY(array, 0); PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext)); }
/*----------------------------------------------------------------------------- * array_push : * push an element onto either end of a one-dimensional array *---------------------------------------------------------------------------- */ Datum array_push(PG_FUNCTION_ARGS) { ArrayType *v; Datum newelem; bool isNull; int *dimv, *lb; ArrayType *result; int indx; Oid element_type; int16 typlen; bool typbyval; char typalign; Oid arg0_typeid = get_fn_expr_argtype(fcinfo->flinfo, 0); Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1); Oid arg0_elemid; Oid arg1_elemid; ArrayMetaState *my_extra; if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data types"))); arg0_elemid = get_element_type(arg0_typeid); arg1_elemid = get_element_type(arg1_typeid); if (arg0_elemid != InvalidOid) { if (PG_ARGISNULL(0)) v = construct_empty_array(arg0_elemid); else v = PG_GETARG_ARRAYTYPE_P(0); isNull = PG_ARGISNULL(1); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(1); } else if (arg1_elemid != InvalidOid) { if (PG_ARGISNULL(1)) v = construct_empty_array(arg1_elemid); else v = PG_GETARG_ARRAYTYPE_P(1); isNull = PG_ARGISNULL(0); if (isNull) newelem = (Datum) 0; else newelem = PG_GETARG_DATUM(0); } else { /* Shouldn't get here given proper type checking in parser */ ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("neither input type is an array"))); PG_RETURN_NULL(); /* keep compiler quiet */ } element_type = ARR_ELEMTYPE(v); if (ARR_NDIM(v) == 1) { lb = ARR_LBOUND(v); dimv = ARR_DIMS(v); if (arg0_elemid != InvalidOid) { /* append newelem */ int ub = dimv[0] + lb[0] - 1; indx = ub + 1; /* overflow? */ if (indx < ub) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } else { /* prepend newelem */ indx = lb[0] - 1; /* overflow? */ if (indx > lb[0]) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); } } else if (ARR_NDIM(v) == 0) indx = 1; else ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("argument must be empty or one-dimensional array"))); /* * We arrange to look up info about element type only once per series of * calls, assuming the element type doesn't change underneath us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { /* Get info about element type */ get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); my_extra->element_type = element_type; } typlen = my_extra->typlen; typbyval = my_extra->typbyval; typalign = my_extra->typalign; result = array_set(v, 1, &indx, newelem, isNull, -1, typlen, typbyval, typalign); /* * Readjust result's LB to match the input's. This does nothing in the * append case, but it's the simplest way to implement the prepend case. */ if (ARR_NDIM(v) == 1) ARR_LBOUND(result)[0] = ARR_LBOUND(v)[0]; PG_RETURN_ARRAYTYPE_P(result); }
Datum alpine_miner_lr_ca_he_de_accum(PG_FUNCTION_ARGS) { ArrayType *beta_arg, *columns_arg, *result; float8 *beta_data, *columns_data, *result_data; int beta_count, columns_count, result_count; int size; bool add_intercept_arg; double weight_arg; int y_arg; double fitness = 0.0; double gx = 0.0; double pi = 0.0; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5)){ PG_RETURN_NULL(); } result = PG_GETARG_ARRAYTYPE_P(0); beta_arg = PG_GETARG_ARRAYTYPE_P(1); columns_arg = PG_GETARG_ARRAYTYPE_P(2); add_intercept_arg = PG_GETARG_BOOL(3); weight_arg = PG_GETARG_FLOAT8(4); y_arg = PG_GETARG_INT32(5); result_data = (float8*) ARR_DATA_PTR(result); beta_data = (float8*) ARR_DATA_PTR(beta_arg); columns_data = (float8*) ARR_DATA_PTR(columns_arg); result_count = ARR_DIMS(result)[0]; beta_count = ARR_DIMS(beta_arg)[0]; columns_count = ARR_DIMS(columns_arg)[0]; // float8 * column_array_data = (float8*) ARR_DATA_PTR(column_array); if (result_count == 1){ result_count = beta_count *(beta_count+1)/2 + beta_count + 1; size = result_count * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); result = (ArrayType *) palloc(size); SET_VARSIZE(result, size); result->ndim = 1; result->dataoffset = 0; result->elemtype = FLOAT8OID; ARR_DIMS(result)[0] = result_count; ARR_LBOUND(result)[0] = 1; result_data = (float8*) ARR_DATA_PTR(result); memset(result_data, 0, result_count * sizeof(float8)); } pi = alpine_miner_compute_pi(beta_data, beta_count, columns_data, columns_count, add_intercept_arg); alpine_miner_compute_hessian(beta_count,beta_data,columns_data, result_data ,weight_arg, add_intercept_arg, pi); alpine_miner_compute_derivative(columns_count,columns_data, &result_data[beta_count *(beta_count+1)/2] ,weight_arg, y_arg, add_intercept_arg, pi); if (y_arg == 1) { fitness = log(pi); } else { fitness = log(1.0 - pi); } fitness *= weight_arg; result_data[result_count - 1] = fitness + result_data[result_count - 1]; PG_RETURN_ARRAYTYPE_P(result); }
Datum #else // _MSC_VER PGDLLEXPORT Datum #endif MY_FUNCTION_NAME(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; uint32_t call_cntr; uint32_t max_calls; TupleDesc tuple_desc; /**************************************************************************/ /* MODIFY AS NEEDED */ /* */ MY_RETURN_VALUE_TYPE *result_tuples = 0; size_t result_count = 0; /* */ /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /**********************************************************************/ /* MODIFY AS NEEDED */ /* MY_QUERY_LINE1 **********************************************************************/ PGR_DBG("Initializing arrays"); int64_t* end_vidsArr; size_t size_end_vidsArr; end_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_end_vidsArr, PG_GETARG_ARRAYTYPE_P(2)); PGR_DBG("targetsArr size %ld ", size_end_vidsArr); PGR_DBG("Calling process"); // Code standard: // Use same order as in the query // Pass the array and it's size on the same line process( pgr_text2char(PG_GETARG_TEXT_P(0)), PG_GETARG_INT64(1), end_vidsArr, size_end_vidsArr, PG_GETARG_BOOL(3), &result_tuples, &result_count); // while developing leave the message as a reminder PGR_DBG("Cleaning arrays using free(<array-name>)"); free(end_vidsArr); /* */ /*******************************************************************************/ funcctx->max_calls = (uint32_t) result_count; funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; tuple_desc = funcctx->tuple_desc; result_tuples = (MY_RETURN_VALUE_TYPE*) funcctx->user_fctx; if (call_cntr < max_calls) { HeapTuple tuple; Datum result; Datum *values; bool* nulls; /*******************************************************************************/ /* MODIFY!!!!! */ /* This has to match you ouput otherwise the server crashes */ /* MY_QUERY_LINE2 ********************************************************************************/ values = palloc(8 * sizeof(Datum)); nulls = palloc(8 * sizeof(bool)); size_t i; for(i = 0; i < 8; ++i) { nulls[i] = false; } // postgres starts counting from 1 values[0] = Int32GetDatum(call_cntr + 1); values[1] = Int32GetDatum(result_tuples[call_cntr].seq); values[2] = Int64GetDatum(result_tuples[call_cntr].start_id); values[3] = Int64GetDatum(result_tuples[call_cntr].end_id); values[4] = Int64GetDatum(result_tuples[call_cntr].node); values[5] = Int64GetDatum(result_tuples[call_cntr].edge); values[6] = Float8GetDatum(result_tuples[call_cntr].cost); values[7] = Float8GetDatum(result_tuples[call_cntr].agg_cost); /*******************************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { // cleanup if (result_tuples) free(result_tuples); SRF_RETURN_DONE(funcctx); } }
Datum sampleNewTopics(PG_FUNCTION_ARGS) { int32 i, widx, wtopic, rtopic; ArrayType * doc_arr = PG_GETARG_ARRAYTYPE_P(0); ArrayType * topics_arr = PG_GETARG_ARRAYTYPE_P(1); ArrayType * topic_d_arr = PG_GETARG_ARRAYTYPE_P(2); ArrayType * global_count_arr = PG_GETARG_ARRAYTYPE_P(3); ArrayType * topic_counts_arr = PG_GETARG_ARRAYTYPE_P(4); int32 num_topics = PG_GETARG_INT32(5); int32 dsize = PG_GETARG_INT32(6); float8 alpha = PG_GETARG_FLOAT8(7); float8 eta = PG_GETARG_FLOAT8(8); if (ARR_NULLBITMAP(doc_arr) || ARR_NDIM(doc_arr) != 1 || ARR_ELEMTYPE(doc_arr) != INT4OID || ARR_NDIM(topics_arr) != 1 || ARR_ELEMTYPE(topics_arr) != INT4OID || ARR_NULLBITMAP(topic_d_arr) || ARR_NDIM(topic_d_arr) != 1 || ARR_ELEMTYPE(topic_d_arr) != INT4OID || ARR_NULLBITMAP(global_count_arr) || ARR_NDIM(global_count_arr) != 1 || ARR_ELEMTYPE(global_count_arr) != INT4OID || ARR_NULLBITMAP(topic_counts_arr) || ARR_NDIM(topic_counts_arr) != 1 || ARR_ELEMTYPE(topic_counts_arr) != INT4OID) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); // the document array int32 * doc = (int32 *)ARR_DATA_PTR(doc_arr); int32 len = ARR_DIMS(doc_arr)[0]; // array giving topic assignment to each word in document int32 * topics = (int32 *)ARR_DATA_PTR(topics_arr); // distribution of topics in document int32 * topic_d = (int32 *)ARR_DATA_PTR(topic_d_arr); // the word-topic count matrix int32 * global_count = (int32 *)ARR_DATA_PTR(global_count_arr); // total number of words assigned to each topic in the whole corpus int32 * topic_counts = (int32 *)ARR_DATA_PTR(topic_counts_arr); ArrayType * ret_topics_arr, * ret_topic_d_arr; int32 * ret_topics, * ret_topic_d; Datum * arr1 = palloc0(len * sizeof(Datum)); ret_topics_arr = construct_array(arr1,len,INT4OID,4,true,'i'); ret_topics = (int32 *)ARR_DATA_PTR(ret_topics_arr); Datum * arr2 = palloc0(num_topics * sizeof(Datum)); ret_topic_d_arr = construct_array(arr2,num_topics,INT4OID,4,true,'i'); ret_topic_d = (int32 *)ARR_DATA_PTR(ret_topic_d_arr); for (i=0; i!=len; i++) { widx = doc[i]; if (widx < 1 || widx > dsize) ereport (ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); wtopic = topics[i]; rtopic = sampleTopic(num_topics,widx,wtopic,global_count, topic_d,topic_counts,alpha,eta); // <sampleNewTopics error checking> ret_topics[i] = rtopic; ret_topic_d[rtopic-1]++; } Datum values[2]; values[0] = PointerGetDatum(ret_topics_arr); values[1] = PointerGetDatum(ret_topic_d_arr); TupleDesc tuple; if (get_call_result_type(fcinfo, NULL, &tuple) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode( ERRCODE_FEATURE_NOT_SUPPORTED ), errmsg( "function returning record called in context " "that cannot accept type record" ))); tuple = BlessTupleDesc(tuple); bool * isnulls = palloc0(2 * sizeof(bool)); HeapTuple ret = heap_form_tuple(tuple, values, isnulls); if (isnulls[0] || isnulls[1]) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("function \"%s\" produced null results", format_procedure(fcinfo->flinfo->fn_oid),i))); PG_RETURN_DATUM(HeapTupleGetDatum(ret)); }
Datum generate_sparse_vector(PG_FUNCTION_ARGS) { SvecType *output_sfv; int16_t typlen; bool typbyval; char typalign; bool *nulls; if (PG_NARGS() != 3) elog(ERROR, "Invalid number of arguments."); ArrayType *term_index = PG_GETARG_ARRAYTYPE_P(0); ArrayType *term_count = PG_GETARG_ARRAYTYPE_P(1); int64_t dict_size = PG_GETARG_INT64(2); /* Check if arrays have null entries */ if (ARR_HASNULL(term_index) || ARR_HASNULL(term_count)) elog(ERROR, "One or both of the argument arrays has one or more null entries."); if (dict_size <= 0) elog(ERROR, "Dictionary size cannot be zero or negative."); /* Check if any of the argument arrays is empty */ if ((ARR_NDIM(term_index) == 0) || (ARR_NDIM(term_count) == 0)) elog(ERROR, "One or more argument arrays is empty."); int term_index_nelems = ARR_DIMS(term_index)[0]; int term_count_nelems = ARR_DIMS(term_count)[0]; /* If no. of elements in the arrays are not equal, throw an error */ if (term_index_nelems != term_count_nelems) elog(ERROR, "No. of elements in the argument arrays are not equal."); Datum *term_index_data; Datum *term_count_data; /* Deconstruct the arrays */ get_typlenbyvalalign(INT8OID, &typlen, &typbyval, &typalign); deconstruct_array(term_index, INT8OID, typlen, typbyval, typalign, &term_index_data, &nulls, &term_index_nelems); get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign); deconstruct_array(term_count, FLOAT8OID, typlen, typbyval, typalign, &term_count_data, &nulls, &term_count_nelems); /* Check if term index array has indexes in proper order or not */ for(int i = 0; i < term_index_nelems; i++) { if (DatumGetInt64(term_index_data[i]) < 0 || DatumGetInt64(term_index_data[i]) >= dict_size) elog(ERROR, "Term indexes must range from 0 to total number of elements in the dictonary - 1."); } float8 *histogram = (float8 *)palloc0(sizeof(float8) * dict_size); for (int k = 0; k < dict_size; k++) { histogram[k] = 0; } for (int i = 0; i < term_index_nelems; i++) { uint64_t idx = DatumGetInt64(term_index_data[i]); histogram[idx] += DatumGetFloat8(term_count_data[i]); } output_sfv = svec_from_float8arr(histogram, dict_size); pfree(histogram); PG_RETURN_POINTER(output_sfv); }
/* * pivot_accum() - Pivot and accumulate */ static Datum oid_pivot_accum(FunctionCallInfo fcinfo, Oid type) { ArrayType *data; ArrayType *labels; text *attr; int i; /* Simple argument validation */ if (PG_NARGS() != 4) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("pivot_accum called with %d input arguments", PG_NARGS()))); if (PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3)) { if (PG_ARGISNULL(0)) PG_RETURN_NULL(); PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(0)); } labels = PG_GETARG_ARRAYTYPE_P(1); attr = PG_GETARG_TEXT_P(2); /* Do nothing if the attr isn't in the labels array. */ if ((i = pivot_find(labels, attr)) < 0) { if (PG_ARGISNULL(0)) PG_RETURN_NULL(); PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(0)); } /* Get the data array, or make it if null */ if (!PG_ARGISNULL(0)) { data = PG_GETARG_ARRAYTYPE_P(0); Assert(ARR_DIMS(labels)[0] == ARR_DIMS(data)[0]); } else { int elsize, size, nelem; switch (type) { case INT4OID: elsize = 4; break; case INT8OID: case FLOAT8OID: elsize = 8; break; default: elsize = 0; /* Fixes complier warnings */ Assert(false); } nelem = ARR_DIMS(labels)[0]; size = nelem * elsize + ARR_OVERHEAD_NONULLS(1); data = (ArrayType *) palloc(size); SET_VARSIZE(data, size); data->ndim = 1; data->dataoffset = 0; data->elemtype = type; ARR_DIMS(data)[0] = nelem; ARR_LBOUND(data)[0] = 1; memset(ARR_DATA_PTR(data), 0, nelem * elsize); } /* * Should we think about upconverting the arrays? Or is the assumption that * the pivot isn't usually doing much aggregation? */ switch (type) { case INT4OID: { int32 *datap = (int32*) ARR_DATA_PTR(data); int32 value = PG_GETARG_INT32(3); datap[i] += value; break; } case INT8OID: { int64 *datap = (int64*) ARR_DATA_PTR(data); int64 value = PG_GETARG_INT64(3); datap[i] += value; break; } case FLOAT8OID: { float8 *datap = (float8*) ARR_DATA_PTR(data); float8 value = PG_GETARG_FLOAT8(3); datap[i] += value; break; } default: Assert(false); } PG_RETURN_ARRAYTYPE_P(data); }
Datum __vcrf_max_top1_array(PG_FUNCTION_ARGS) { ArrayType *v1 ; // , // *v2; ArrayType *result; // int *dims, // *lbs, int ndims, // nitems, ndatabytes, nbytes; int nitems1; // int *dims1, // *lbs1, // ndims1, // nitems1, // ndatabytes1; // int *dims2, // *lbs2, // ndims2, // nitems2, // ndatabytes2; int i; // char *dat1, // *dat2; // bits8 *bitmap1, // *bitmap2; Oid element_type; // Oid element_type1; // Oid element_type2; int32 dataoffset; if (PG_ARGISNULL(0)) abort(); v1 = PG_GETARG_ARRAYTYPE_P(0); element_type = ARR_ELEMTYPE(v1); nitems1 = ARR_DIMS(v1)[1]; if (nitems1 == 0) abort(); /* new array is the same as v1 for top 1 only !! */ ndims = 2; ndatabytes = 3*sizeof(int); dataoffset = 0; /* marker for no null bitmap */ nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims); result = (ArrayType *) palloc(nbytes); SET_VARSIZE(result, nbytes); result->ndim = ndims; result->dataoffset = dataoffset; result->elemtype = element_type; ARR_DIMS(result)[0]=3; /* num elements in first dim */ ARR_DIMS(result)[1]=1; /* num elements in second dim */ /* postgres arrays can be index from any start position eg: * int[-5:14]. this is unlike c, where index always starts at 0 */ ARR_LBOUND(result)[0]=1; /* index of the first dim starts at .. */ ARR_LBOUND(result)[1]=1; /* index of second dim starts at ... */ // do top1 calculation here for(i = 0; i < nitems1; i++) { if (i == 0 || ((int*)ARR_DATA_PTR(v1))[0*nitems1+i] > ((int*)ARR_DATA_PTR(v1))[0*nitems1+((int*)ARR_DATA_PTR(result))[0*1+0]]) { ((int*)ARR_DATA_PTR(result))[0*1+0] = i; ((int*)ARR_DATA_PTR(result))[1*1+0] = ((int*)ARR_DATA_PTR(v1))[1*nitems1+i]; ((int*)ARR_DATA_PTR(result))[2*1+0] = ((int*)ARR_DATA_PTR(v1))[0*nitems1+i]; } } PG_RETURN_ARRAYTYPE_P(result); }
PGDLLEXPORT Datum max_flow_many_to_many(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; /**************************************************************************/ pgr_flow_t *result_tuples = 0; size_t result_count = 0; /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /**********************************************************************/ process( text_to_cstring(PG_GETARG_TEXT_P(0)), PG_GETARG_ARRAYTYPE_P(1), PG_GETARG_ARRAYTYPE_P(2), text_to_cstring(PG_GETARG_TEXT_P(3)), PG_GETARG_BOOL(4), &result_tuples, &result_count); /* */ /**********************************************************************/ #if PGSQL_VERSION > 95 funcctx->max_calls = result_count; #else funcctx->max_calls = (uint32_t)result_count; #endif funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); } funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); tuple_desc = funcctx->tuple_desc; result_tuples = (pgr_flow_t *) funcctx->user_fctx; if (funcctx->call_cntr < funcctx->max_calls) { HeapTuple tuple; Datum result; Datum *values; bool *nulls; size_t call_cntr = funcctx->call_cntr; /**********************************************************************/ /* MODIFY AS NEEDED */ values = palloc(6 * sizeof(Datum)); nulls = palloc(6 * sizeof(bool)); size_t i; for (i = 0; i < 6; ++i) { nulls[i] = false; } values[0] = Int32GetDatum(call_cntr + 1); values[1] = Int64GetDatum(result_tuples[call_cntr].edge); values[2] = Int64GetDatum(result_tuples[call_cntr].source); values[3] = Int64GetDatum(result_tuples[call_cntr].target); values[4] = Int64GetDatum(result_tuples[call_cntr].flow); values[5] = Int64GetDatum(result_tuples[call_cntr].residual_capacity); /**********************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { SRF_RETURN_DONE(funcctx); } }
Datum array_multi_index( PG_FUNCTION_ARGS ) { if( PG_ARGISNULL(0) ) { PG_RETURN_NULL(); } if( PG_ARGISNULL(1) ) { PG_RETURN_NULL(); } ArrayType* values = PG_GETARG_ARRAYTYPE_P( 0 ); ArrayType* indices = PG_GETARG_ARRAYTYPE_P( 1 ); Oid values_type = ARR_ELEMTYPE( values ); int16 values_width; bool values_passbyvalue; char values_alignmentcode; Datum* values_content; bool* values_nullflags; int values_length; get_typlenbyvalalign( values_type, &values_width, &values_passbyvalue, &values_alignmentcode ); deconstruct_array( values, values_type, values_width, values_passbyvalue, values_alignmentcode, &values_content, &values_nullflags, &values_length ); Oid indices_type = ARR_ELEMTYPE( indices ); int16 indices_width; bool indices_passbyvalue; char indices_alignmentcode; Datum* indices_content; bool* indices_nullflags; int indices_length; get_typlenbyvalalign( indices_type, &indices_width, &indices_passbyvalue, &indices_alignmentcode ); deconstruct_array( indices, indices_type, indices_width, indices_passbyvalue, indices_alignmentcode, &indices_content, &indices_nullflags, &indices_length ); Oid results_type = values_type; int16 results_width = values_width; bool results_passbyvalue = values_passbyvalue; char results_alignmentcode = values_alignmentcode; Datum* results_content = (Datum *)palloc( sizeof(Datum) * indices_length ); bool* results_nullflags = (bool *)palloc0( sizeof(bool) * indices_length ); int results_length = indices_length; int i; for( i = 0; i < indices_length; ++i ) { if( indices_nullflags[i] ) { results_content[i] = 0; results_nullflags[i] = true; } else if( indices_content[i] - 1 >= (long unsigned)values_length ) { results_content[i] = 0; results_nullflags[i] = true; } else { results_content[i] = values_content[ indices_content[i] - 1 ]; results_nullflags[i] = values_nullflags[ indices_content[i] - 1 ]; } } int dims[1]; int lbs[1]; dims[0] = results_length; lbs[0] = 1; ArrayType* results = construct_md_array( results_content, results_nullflags, 1, dims, lbs, results_type, results_width, results_passbyvalue, results_alignmentcode ); pfree( results_content ); pfree( results_nullflags ); PG_RETURN_ARRAYTYPE_P( results ); }
Datum __vcrf_sum_array(PG_FUNCTION_ARGS) { ArrayType *v1, *v2; ArrayType *result; // int *dims, // *lbs, int ndims, // nitems, ndatabytes, nbytes; int nitems1, nitems2; // int *dims1, // *lbs1, // ndims1, // nitems1, // ndatabytes1; // int *dims2, // *lbs2, // ndims2, // nitems2, // ndatabytes2; int i; // char *dat1, // *dat2; // bits8 *bitmap1, // *bitmap2; Oid element_type; // Oid element_type1; // Oid element_type2; int32 dataoffset; int spos; if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) abort(); // pointers to the postgres arrays v1 = PG_GETARG_ARRAYTYPE_P(0); v2 = PG_GETARG_ARRAYTYPE_P(1); // postgres type of elements in an array element_type = ARR_ELEMTYPE(v1); // number of items in the arrays nitems1 = ARR_DIMS(v1)[0]; nitems2 = ARR_DIMS(v2)[0]; // if (nitems1 == 0 || nitems2 == 0 || nitems2 % nitems1 != 0) // abort(); /* new array is the same as v1 for top 1 only !! */ ndims = ARR_NDIM(v1); ndatabytes = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1); dataoffset = 0; /* marker for no null bitmap */ nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims); result = (ArrayType *) palloc(nbytes); SET_VARSIZE(result, nbytes); result->ndim = ndims; result->dataoffset = dataoffset; result->elemtype = element_type; for(i=0;i<ndims;i++) { ARR_DIMS(result)[i]=ARR_DIMS(v1)[i]; ARR_LBOUND(result)[i]=ARR_LBOUND(v1)[i]; } // array v2 can either have nitems1 or nitems1*nitems1 or (nitems1+1)*nitems1 items, because of the -1 arrays from MR // for the first and third case we want to skip the first nitems1 items //int spos=0; spos = nitems2 % (nitems1*nitems1); for(i=0; i<nitems1; i++) ((int*)ARR_DATA_PTR(result))[i] = 0; // do sum over all possible value of y' calculation here for(i = spos; i < nitems2; i++) { int k = (i-spos) / nitems1; int k_rem = i % nitems1; int new_score = ((int*)ARR_DATA_PTR(v1))[0*nitems1+k] + ((int*)ARR_DATA_PTR(v2))[i]; // 0.5 is for rounding ((int*)ARR_DATA_PTR(result))[0*nitems1+k_rem] = (int)(log(exp(((int*)ARR_DATA_PTR(result))[0*nitems1+k_rem]/1000.0) + exp(new_score/1000.0))*1000.0 + 0.5); } PG_RETURN_ARRAYTYPE_P(result); }
Datum tsp_matrix(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; int call_cntr; int max_calls; TupleDesc tuple_desc; AttInMetadata *attinmeta; DTYPE *matrix; int *tsp_res; int num; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; //int path_count; int ret=-1; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); matrix = get_pgarray(&num, PG_GETARG_ARRAYTYPE_P(0)); ret = solve_tsp(matrix, num, PG_GETARG_INT32(1), // start index PG_GETARG_INT32(2), // end index &tsp_res); pfree(matrix); if (ret < 0) { elog(ERROR, "Error, failed to solve TSP."); } funcctx->max_calls = num; funcctx->user_fctx = tsp_res; /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); funcctx->tuple_desc = BlessTupleDesc(tuple_desc); /* * generate attribute metadata needed later to produce tuples from raw * C strings */ //attinmeta = TupleDescGetAttInMetadata(tuple_desc); //funcctx->attinmeta = attinmeta; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; tuple_desc = funcctx->tuple_desc; tsp_res = funcctx->user_fctx; DBG("Trying to allocate some memory"); DBG("call_cntr = %i, max_calls = %i", call_cntr, max_calls); if (call_cntr < max_calls) { /* do when there is more left to send */ HeapTuple tuple; Datum result; Datum *values; char* nulls; values = palloc(2 * sizeof(Datum)); nulls = palloc(2 * sizeof(char)); values[0] = Int32GetDatum(call_cntr); nulls[0] = ' '; values[1] = Int32GetDatum(tsp_res[call_cntr]); nulls[1] = ' '; DBG("RESULT: %d, %d", call_cntr, tsp_res[call_cntr]); DBG("Heap making"); tuple = heap_formtuple(tuple_desc, values, nulls); DBG("Datum making"); /* make the tuple into a datum */ result = HeapTupleGetDatum(tuple); DBG("RESULT: seq:%d, id:%d", call_cntr, tsp_res[call_cntr]); DBG("Trying to free some memory"); /* clean up (this is not really necessary) */ pfree(values); pfree(nulls); SRF_RETURN_NEXT(funcctx, result); } else { /* do when there is no more left */ DBG("Freeing tsp_res"); free(tsp_res); DBG("Ending function"); SRF_RETURN_DONE(funcctx); } }
/* * SQL function jsonb_object(text[], text[]) * * take separate name and value arrays of text to construct a jsonb object * pairwise. */ Datum jsonb_object_two_arg(PG_FUNCTION_ARGS) { ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0); ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1); int nkdims = ARR_NDIM(key_array); int nvdims = ARR_NDIM(val_array); Datum *key_datums, *val_datums; bool *key_nulls, *val_nulls; int key_count, val_count, i; JsonbInState result; memset(&result, 0, sizeof(JsonbInState)); (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL); if (nkdims > 1 || nkdims != nvdims) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); if (nkdims == 0) goto close_object; deconstruct_array(key_array, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); deconstruct_array(val_array, TEXTOID, -1, false, 'i', &val_datums, &val_nulls, &val_count); if (key_count != val_count) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("mismatched array dimensions"))); for (i = 0; i < key_count; ++i) { JsonbValue v; char *str; int len; if (key_nulls[i]) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed for object key"))); str = TextDatumGetCString(key_datums[i]); len = strlen(str); v.type = jbvString; v.val.string.len = len; v.val.string.val = str; (void) pushJsonbValue(&result.parseState, WJB_KEY, &v); if (val_nulls[i]) { v.type = jbvNull; } else { str = TextDatumGetCString(val_datums[i]); len = strlen(str); v.type = jbvString; v.val.string.len = len; v.val.string.val = str; } (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v); } pfree(key_datums); pfree(key_nulls); pfree(val_datums); pfree(val_nulls); close_object: result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL); PG_RETURN_POINTER(JsonbValueToJsonb(result.res)); }
/* * SQL function jsonb_object(text[]) * * take a one or two dimensional array of text as name value pairs * for a jsonb object. * */ Datum jsonb_object(PG_FUNCTION_ARGS) { ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0); int ndims = ARR_NDIM(in_array); Datum *in_datums; bool *in_nulls; int in_count, count, i; JsonbInState result; memset(&result, 0, sizeof(JsonbInState)); (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL); switch (ndims) { case 0: goto close_object; break; case 1: if ((ARR_DIMS(in_array)[0]) % 2) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array must have even number of elements"))); break; case 2: if ((ARR_DIMS(in_array)[1]) != 2) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array must have two columns"))); break; default: ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); } deconstruct_array(in_array, TEXTOID, -1, false, 'i', &in_datums, &in_nulls, &in_count); count = in_count / 2; for (i = 0; i < count; ++i) { JsonbValue v; char *str; int len; if (in_nulls[i * 2]) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed for object key"))); str = TextDatumGetCString(in_datums[i * 2]); len = strlen(str); v.type = jbvString; v.val.string.len = len; v.val.string.val = str; (void) pushJsonbValue(&result.parseState, WJB_KEY, &v); if (in_nulls[i * 2 + 1]) { v.type = jbvNull; } else { str = TextDatumGetCString(in_datums[i * 2 + 1]); len = strlen(str); v.type = jbvString; v.val.string.len = len; v.val.string.val = str; } (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v); } pfree(in_datums); pfree(in_nulls); close_object: result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL); PG_RETURN_POINTER(JsonbValueToJsonb(result.res)); }
Datum hstore_from_array(PG_FUNCTION_ARGS) { ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0); int ndims = ARR_NDIM(in_array); int count; int4 buflen; HStore *out; Pairs *pairs; Datum *in_datums; bool *in_nulls; int in_count; int i; Assert(ARR_ELEMTYPE(in_array) == TEXTOID); switch (ndims) { case 0: out = hstorePairs(NULL, 0, 0); PG_RETURN_POINTER(out); case 1: if ((ARR_DIMS(in_array)[0]) % 2) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array must have even number of elements"))); break; case 2: if ((ARR_DIMS(in_array)[1]) != 2) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array must have two columns"))); break; default: ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); } deconstruct_array(in_array, TEXTOID, -1, false, 'i', &in_datums, &in_nulls, &in_count); count = in_count / 2; pairs = palloc(count * sizeof(Pairs)); for (i = 0; i < count; ++i) { if (in_nulls[i * 2]) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed for hstore key"))); if (in_nulls[i * 2 + 1]) { pairs[i].key = VARDATA_ANY(in_datums[i * 2]); pairs[i].val = NULL; pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(in_datums[i * 2])); pairs[i].vallen = 4; pairs[i].isnull = true; pairs[i].needfree = false; } else { pairs[i].key = VARDATA_ANY(in_datums[i * 2]); pairs[i].val = VARDATA_ANY(in_datums[i * 2 + 1]); pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(in_datums[i * 2])); pairs[i].vallen = hstoreCheckValLen(VARSIZE_ANY_EXHDR(in_datums[i * 2 + 1])); pairs[i].isnull = false; pairs[i].needfree = false; } } count = hstoreUniquePairs(pairs, count, &buflen); out = hstorePairs(pairs, count, buflen); PG_RETURN_POINTER(out); }
Datum hstore_delete_array(PG_FUNCTION_ARGS) { HStore *hs = PG_GETARG_HS(0); HStore *out = palloc(VARSIZE(hs)); int hs_count = HS_COUNT(hs); char *ps, *bufd, *pd; HEntry *es, *ed; int i, j; int outcount = 0; ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(1); int nkeys; Pairs *key_pairs = hstoreArrayToPairs(key_array, &nkeys); SET_VARSIZE(out, VARSIZE(hs)); HS_SETCOUNT(out, hs_count); /* temporary! */ ps = STRPTR(hs); es = ARRPTR(hs); bufd = pd = STRPTR(out); ed = ARRPTR(out); if (nkeys == 0) { /* return a copy of the input, unchanged */ memcpy(out, hs, VARSIZE(hs)); HS_FIXSIZE(out, hs_count); HS_SETCOUNT(out, hs_count); PG_RETURN_POINTER(out); } /* * this is in effect a merge between hs and key_pairs, both of which are * already sorted by (keylen,key); we take keys from hs only */ for (i = j = 0; i < hs_count;) { int difference; if (j >= nkeys) difference = -1; else { int skeylen = HS_KEYLEN(es, i); if (skeylen == key_pairs[j].keylen) difference = strncmp(HS_KEY(es, ps, i), key_pairs[j].key, key_pairs[j].keylen); else difference = (skeylen > key_pairs[j].keylen) ? 1 : -1; } if (difference > 0) ++j; else if (difference == 0) ++i, ++j; else { HS_COPYITEM(ed, bufd, pd, HS_KEY(es, ps, i), HS_KEYLEN(es, i), HS_VALLEN(es, i), HS_VALISNULL(es, i)); ++outcount; ++i; } } HS_FINALIZE(out, outcount, bufd, pd); PG_RETURN_POINTER(out); }
Datum gin_extract_jsonb_query(PG_FUNCTION_ARGS) { int32 *nentries = (int32 *) PG_GETARG_POINTER(1); StrategyNumber strategy = PG_GETARG_UINT16(2); int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); Datum *entries; if (strategy == JsonbContainsStrategyNumber) { /* Query is a jsonb, so just apply gin_extract_jsonb... */ entries = (Datum *) DatumGetPointer(DirectFunctionCall2(gin_extract_jsonb, PG_GETARG_DATUM(0), PointerGetDatum(nentries))); /* ...although "contains {}" requires a full index scan */ if (*nentries == 0) *searchMode = GIN_SEARCH_MODE_ALL; } else if (strategy == JsonbExistsStrategyNumber) { /* Query is a text string, which we treat as a key */ text *query = PG_GETARG_TEXT_PP(0); *nentries = 1; entries = (Datum *) palloc(sizeof(Datum)); entries[0] = make_text_key(JGINFLAG_KEY, VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query)); } else if (strategy == JsonbExistsAnyStrategyNumber || strategy == JsonbExistsAllStrategyNumber) { /* Query is a text array; each element is treated as a key */ ArrayType *query = PG_GETARG_ARRAYTYPE_P(0); Datum *key_datums; bool *key_nulls; int key_count; int i, j; deconstruct_array(query, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); entries = (Datum *) palloc(sizeof(Datum) * key_count); for (i = 0, j = 0; i < key_count; i++) { /* Nulls in the array are ignored */ if (key_nulls[i]) continue; entries[j++] = make_text_key(JGINFLAG_KEY, VARDATA_ANY(key_datums[i]), VARSIZE_ANY_EXHDR(key_datums[i])); } *nentries = j; /* ExistsAll with no keys should match everything */ if (j == 0 && strategy == JsonbExistsAllStrategyNumber) *searchMode = GIN_SEARCH_MODE_ALL; } else { elog(ERROR, "unrecognized strategy number: %d", strategy); entries = NULL; /* keep compiler quiet */ } PG_RETURN_POINTER(entries); }
/* * nb_classify_accum - Naive Bayesian Classification Accumulator */ Datum nb_classify_accum(PG_FUNCTION_ARGS) { nb_classify_state state; TupleDesc resultDesc; int i; int nclasses; ArrayType *classes; /* arg[1] */ int64 attr_count; /* arg[2] */ ArrayType *class_count; /* arg[3] */ ArrayType *class_total; /* arg[4] */ HeapTuple result; Datum resultDatum[3]; bool resultNull[3]; bool skip; int64 *class_data; int64 *total_data; float8 *prior_data; int64 *stotal_data; /* Check input parameters */ if (PG_NARGS() != 5) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify_accum called with %d arguments", PG_NARGS()))); } /* Skip rows with NULLs */ if (PG_ARGISNULL(1) || PG_ARGISNULL(3) || PG_ARGISNULL(4)) { if (PG_ARGISNULL(0)) PG_RETURN_NULL(); PG_RETURN_DATUM(PG_GETARG_DATUM(0)); } classes = PG_GETARG_ARRAYTYPE_P(1); attr_count = PG_ARGISNULL(2) ? 0 : PG_GETARG_INT64(2); class_count = PG_GETARG_ARRAYTYPE_P(3); class_total = PG_GETARG_ARRAYTYPE_P(4); if (ARR_NDIM(classes) != 1 || ARR_NDIM(class_count) != 1 || ARR_NDIM(class_total) != 1) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify cannot accumulate multidimensional arrays"))); } /* All three arrays must be equal cardinality */ nclasses = ARR_DIMS(classes)[0]; if (ARR_DIMS(class_count)[0] != nclasses || ARR_DIMS(class_total)[0] != nclasses) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify: non-conformable arrays"))); } class_data = (int64*) ARR_DATA_PTR(class_count); total_data = (int64*) ARR_DATA_PTR(class_total); /* It is an error for class_data, total_data, or attr_count to be a negative number */ if (attr_count < 0) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify: attr_count value must be >= 0"))); } skip = false; for (i = 0; i < nclasses; i++) { if (class_data[i] < 0) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify: class_data values must be >= 0"))); } if (total_data[i] < 0) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify: total_data values must be >= 0"))); } if (class_data[i] > total_data[i]) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("nb_classify: class_data values must be <= total_data"))); } /* * If we do not have an adjustment value and any class has a zero value * then we must skip this row, otherwise we will try to calculate ln(0) */ if (attr_count == 0 && class_data[i] == 0) { skip = true; } } if (skip) { PG_RETURN_DATUM(PG_GETARG_DATUM(0)); } /* Get/create the accumulation state */ if (!PG_ARGISNULL(0)) { HeapTupleHeader tup; tup = (fcinfo->context && IsA(fcinfo->context, AggState)) ? PG_GETARG_HEAPTUPLEHEADER(0) : PG_GETARG_HEAPTUPLEHEADER_COPY(0); get_nb_state(tup, &state, nclasses); } else { /* Construct the state arrays */ int size; /* allocate memory and copy the classes array */ size = VARSIZE(classes); state.classes = (ArrayType *) palloc(size); SET_VARSIZE(state.classes, size); memcpy(state.classes, classes, size); /* allocate memory and construct the accumulator array */ size = ARR_OVERHEAD_NONULLS(1) + nclasses * sizeof(float8); state.accum = (ArrayType *) palloc(size); SET_VARSIZE(state.accum, size); state.accum->ndim = 1; state.accum->dataoffset = 0; ARR_ELEMTYPE(state.accum) = FLOAT8OID; ARR_DIMS(state.accum)[0] = nclasses; ARR_LBOUND(state.accum)[0] = 1; prior_data = (float8*) ARR_DATA_PTR(state.accum); for (i = 0; i < nclasses; i++) prior_data[i] = 0; /* allocate memory and construct the total array */ size = ARR_OVERHEAD_NONULLS(1) + nclasses * sizeof(int64); state.total = (ArrayType *) palloc(size); SET_VARSIZE(state.total, size); state.total->ndim = 1; state.total->dataoffset = 0; ARR_ELEMTYPE(state.total) = INT8OID; ARR_DIMS(state.total)[0] = nclasses; ARR_LBOUND(state.total)[0] = 1; stotal_data = (int64*) ARR_DATA_PTR(state.total); for (i = 0; i < nclasses; i++) stotal_data[i] = 0; } /* Adjust the prior based on the current input row */ prior_data = (float8*) ARR_DATA_PTR(state.accum); stotal_data = (int64*) ARR_DATA_PTR(state.total); for (i = 0; i < nclasses; i++) { /* * Calculate the accumulation value for the classifier * * The logical calculation is: * product((class[i]+1)/(total_data[i]+attr_count)) * * Instead of this calculation we calculate: * sum(ln((class[i]+1)/(total_data[i]+attr_count))) * * The reason for this is to increase the numerical stability of * the algorithm. * * Since the ln(0) is undefined we want to increment the count * for all classes. * * This get's a bit more complicated for the denominator which * needs to know how many values there are for this attribute * so that we keep the total probability for the attribute = 1. * To handle this the aggregation function should be passed the * number of distinct values for the aggregate it is computing. * * If for some reason this value is not present, or < 1 then we * just switch to non-adjusted calculations. In this case we * will simply skip over any row that has a 0 count on any * class_data index. (handled above) */ if (attr_count > 1) prior_data[i] += log((class_data[i]+1)/(float8)(total_data[i] + attr_count)); else prior_data[i] += log(class_data[i]/(float8)total_data[i]); /* * The total array should be constant throughout, but if not it should * reflect the maximum values encountered */ if (total_data[i] > stotal_data[i]) stotal_data[i] = total_data[i]; } /* Construct the return tuple */ if (get_call_result_type(fcinfo, NULL, &resultDesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); BlessTupleDesc(resultDesc); resultDatum[0] = PointerGetDatum(state.classes); resultDatum[1] = PointerGetDatum(state.accum); resultDatum[2] = PointerGetDatum(state.total); resultNull[0] = false; resultNull[1] = false; resultNull[2] = false; result = heap_form_tuple(resultDesc, resultDatum, resultNull); PG_RETURN_DATUM(HeapTupleGetDatum(result)); }
Datum argmin(PG_FUNCTION_ARGS) { int i=0; // iteration int min_i = 0; // marker // just use a double double s = 0; // marked value // Unwrap ArrayType *anyArray = PG_GETARG_ARRAYTYPE_P(0); Oid oid = ARR_ELEMTYPE(anyArray); // there is clearly a better way to do the below // in a general way, but that will have to wait // I need should be able to iterate with typelen // int16 typlen; // bool typbyval; // char typalign; // get_typlenbyvalalign(oid,&typlen,&typbyval, &typalign); // Datum el = array_ref(anyArray, ARR_NDIM(anyArray), i, -1, typlen, typbyval, typalign, &isNull ); if(oid == INT2OID) { int16 *a = (int16 *) ARR_DATA_PTR(anyArray); s = a[i]; // move through it for(++i; i< ARR_DIMS(anyArray)[0]; ++i) { if (a[i] < s) { s = a[i]; min_i = i; } } } else if (oid == INT4OID) { int32 *a = (int32 *) ARR_DATA_PTR(anyArray); s = a[i]; // move through it for(++i; i< ARR_DIMS(anyArray)[0]; ++i) { if (a[i] < s) { s = a[i]; min_i = i; } } } else if (oid == INT8OID) { int64 *a = (int64 *) ARR_DATA_PTR(anyArray); s = a[i]; // move through it for(++i; i< ARR_DIMS(anyArray)[0]; ++i) { if (a[i] < s) { s = a[i]; min_i = i; } } } else if (oid == FLOAT4OID) { float4 *a = (float4 *) ARR_DATA_PTR(anyArray); s = a[i]; // move through it for(++i; i< ARR_DIMS(anyArray)[0]; ++i) { if (a[i] < s) { s = a[i]; min_i = i; } } } else if (oid == FLOAT8OID) { float8 *a = (float8 *) ARR_DATA_PTR(anyArray); s = a[i]; // move through it for(++i; i< ARR_DIMS(anyArray)[0]; ++i) { if (a[i] < s) { s = a[i]; min_i = i; } } } else if(oid == NUMERICOID) { ereport(INFO, (errmsg_internal("Numeric[] not implemented: %d", oid))); } else { ereport(INFO, (errmsg_internal("wrong types: %d", oid))); } PG_RETURN_INT32( min_i + 1 ); }
Datum gin_extract_hstore_query(PG_FUNCTION_ARGS) { int32 *nentries = (int32 *) PG_GETARG_POINTER(1); StrategyNumber strategy = PG_GETARG_UINT16(2); int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); Datum *entries; if (strategy == HStoreContainsStrategyNumber) { /* Query is an hstore, so just apply gin_extract_hstore... */ entries = (Datum *) DatumGetPointer(DirectFunctionCall2(gin_extract_hstore, PG_GETARG_DATUM(0), PointerGetDatum(nentries))); /* ... except that "contains {}" requires a full index scan */ if (entries == NULL) *searchMode = GIN_SEARCH_MODE_ALL; } else if (strategy == HStoreExistsStrategyNumber) { text *query = PG_GETARG_TEXT_PP(0); text *item; *nentries = 1; entries = (Datum *) palloc(sizeof(Datum)); item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG); entries[0] = PointerGetDatum(item); } else if (strategy == HStoreExistsAnyStrategyNumber || strategy == HStoreExistsAllStrategyNumber) { ArrayType *query = PG_GETARG_ARRAYTYPE_P(0); Datum *key_datums; bool *key_nulls; int key_count; int i, j; text *item; deconstruct_array(query, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); entries = (Datum *) palloc(sizeof(Datum) * key_count); for (i = 0, j = 0; i < key_count; ++i) { /* Nulls in the array are ignored, cf hstoreArrayToPairs */ if (key_nulls[i]) continue; item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG); entries[j++] = PointerGetDatum(item); } *nentries = j; /* ExistsAll with no keys should match everything */ if (j == 0 && strategy == HStoreExistsAllStrategyNumber) *searchMode = GIN_SEARCH_MODE_ALL; } else { elog(ERROR, "unrecognized strategy number: %d", strategy); entries = NULL; /* keep compiler quiet */ } PG_RETURN_POINTER(entries); }
Datum text_unpivot(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; unpivot_fctx *fctx; MemoryContext oldcontext; Datum d[2]; bool isna[2]; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { TupleDesc tupdesc; ArrayType *labels; ArrayType *data; Oid eltype1; Oid eltype2; /* see if we were given an explicit step size */ if (PG_NARGS() != 2) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("number of parameters != 2"))); /* * Type check inputs: * 0: label text[] * 1: value anyarray */ eltype1 = get_fn_expr_argtype(fcinfo->flinfo, 0); eltype2 = get_fn_expr_argtype(fcinfo->flinfo, 1); if (!OidIsValid(eltype1)) elog(ERROR, "could not determine data type of input 'label'"); if (!OidIsValid(eltype2)) elog(ERROR, "could not determine data type of input 'value'"); /* Strict function, return null on null input */ if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) PG_RETURN_NULL(); /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); funcctx->tuple_desc = BlessTupleDesc(tupdesc); /* allocate memory for user context */ fctx = (unpivot_fctx *) palloc(sizeof(unpivot_fctx)); /* Use fctx to keep state from call to call */ labels = PG_GETARG_ARRAYTYPE_P(0); data = PG_GETARG_ARRAYTYPE_P(1); array_loop(labels, ARR_LBOUND(labels)[0], &fctx->label_iter); array_loop(data, ARR_LBOUND(labels)[0], &fctx->data_iter); funcctx->user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); /* get the saved state and use current as the result for this iteration */ fctx = (unpivot_fctx*) funcctx->user_fctx; if (array_next(&fctx->label_iter, &d[0], &isna[0])) { HeapTuple tuple; array_next(&fctx->data_iter, &d[1], &isna[1]); tuple = heap_form_tuple(funcctx->tuple_desc, d, isna); SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); } else { SRF_RETURN_DONE(funcctx); } }
PGDLLEXPORT Datum MY_FUNCTION_NAME(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; TupleDesc tuple_desc; /**************************************************************************/ /* MODIFY AS NEEDED */ /* */ MY_RETURN_VALUE_TYPE *result_tuples = NULL; size_t result_count = 0; /* */ /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /**********************************************************************/ /* MODIFY AS NEEDED */ /* MY_QUERY_LINE1 **********************************************************************/ PGR_DBG("Calling process"); process( text_to_cstring(PG_GETARG_TEXT_P(0)), PG_GETARG_INT64(1), PG_GETARG_INT64(2), #if 0 /* * handling arrays example */ PG_GETARG_ARRAYTYPE_P(1), PG_GETARG_ARRAYTYPE_P(2), #endif PG_GETARG_BOOL(3), PG_GETARG_BOOL(4), &result_tuples, &result_count); /* */ /**********************************************************************/ #if PGSQL_VERSION > 94 funcctx->max_calls = result_count; #else funcctx->max_calls = (uint32_t)result_count; #endif funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); } funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); tuple_desc = funcctx->tuple_desc; result_tuples = (MY_RETURN_VALUE_TYPE*) funcctx->user_fctx; if (funcctx->call_cntr < funcctx->max_calls) { HeapTuple tuple; Datum result; Datum *values; bool* nulls; /**********************************************************************/ /* MODIFY AS NEEDED */ /* MY_QUERY_LINE2 ***********************************************************************/ values = palloc(6 * sizeof(Datum)); nulls = palloc(6 * sizeof(bool)); size_t i; for (i = 0; i < 6; ++i) { nulls[i] = false; } // postgres starts counting from 1 values[0] = Int32GetDatum(funcctx->call_cntr + 1); values[1] = Int32GetDatum(result_tuples[funcctx->call_cntr].seq); values[2] = Int64GetDatum(result_tuples[funcctx->call_cntr].node); values[3] = Int64GetDatum(result_tuples[funcctx->call_cntr].edge); values[4] = Float8GetDatum(result_tuples[funcctx->call_cntr].cost); values[5] = Float8GetDatum(result_tuples[funcctx->call_cntr].agg_cost); /**********************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { /**********************************************************************/ /* MODIFY AS NEEDED */ PGR_DBG("Clean up code"); /**********************************************************************/ SRF_RETURN_DONE(funcctx); } }
Datum #else // _MSC_VER PGDLLEXPORT Datum #endif many_to_one_dijkstra(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; uint32_t call_cntr; uint32_t max_calls; TupleDesc tuple_desc; /**************************************************************************/ /* MODIFY AS NEEDED */ /* */ General_path_element_t *result_tuples = 0; size_t result_count = 0; /* */ /**************************************************************************/ if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /*********************************************************************/ /* MODIFY AS NEEDED */ // CREATE OR REPLACE FUNCTION pgr_dijkstra( // sql text, // start_vids anyarray, // end_vid BIGINT, // directed BOOLEAN default true, PGR_DBG("Initializing arrays"); int64_t* start_vidsArr; size_t size_start_vidsArr; start_vidsArr = (int64_t*) pgr_get_bigIntArray(&size_start_vidsArr, PG_GETARG_ARRAYTYPE_P(1)); PGR_DBG("start_vidsArr size %ld ", size_start_vidsArr); PGR_DBG("Calling process"); process( pgr_text2char(PG_GETARG_TEXT_P(0)), start_vidsArr, size_start_vidsArr, PG_GETARG_INT64(2), PG_GETARG_BOOL(3), PG_GETARG_BOOL(4), &result_tuples, &result_count); PGR_DBG("Cleaning arrays"); free(start_vidsArr); /* */ /*********************************************************************/ funcctx->max_calls = (uint32_t) result_count; funcctx->user_fctx = result_tuples; if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); } funcctx->tuple_desc = tuple_desc; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; tuple_desc = funcctx->tuple_desc; result_tuples = (General_path_element_t*) funcctx->user_fctx; if (call_cntr < max_calls) { HeapTuple tuple; Datum result; Datum *values; bool* nulls; /*********************************************************************/ /* MODIFY AS NEEDED */ // OUT seq INTEGER, // OUT path_seq INTEGER, // OUT start_vid BIGINT, // OUT end_vid BIGINT, // OUT node BIGINT, // OUT edge BIGINT, // OUT cost FLOAT, // OUT agg_cost FLOAT) values = palloc(7 * sizeof(Datum)); nulls = palloc(7 * sizeof(bool)); size_t i; for (i = 0; i < 7; ++i) { nulls[i] = false; } // postgres starts counting from 1 values[0] = Int32GetDatum(call_cntr + 1); values[1] = Int32GetDatum(result_tuples[call_cntr].seq); values[2] = Int64GetDatum(result_tuples[call_cntr].start_id); values[3] = Int64GetDatum(result_tuples[call_cntr].node); values[4] = Int64GetDatum(result_tuples[call_cntr].edge); values[5] = Float8GetDatum(result_tuples[call_cntr].cost); values[6] = Float8GetDatum(result_tuples[call_cntr].agg_cost); /*********************************************************************/ tuple = heap_form_tuple(tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } else { // cleanup if (result_tuples) free(result_tuples); SRF_RETURN_DONE(funcctx); } }
Datum alpine_miner_nn_ca_o(PG_FUNCTION_ARGS) { ArrayType *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result; Datum *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data; bool *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls; int weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ; Oid result_eltype; int16 result_typlen; bool result_typbyval; char result_typalign; double output_range_arg,output_base_arg; int hidden_layer_number_arg, output_node_no_arg; bool normalize_arg, numerical_label_arg ; int ndims, *dims, *lbs; int i; int j; int k; int all_hidden_node_count; int weight_index; int hidden_node_number_index = 0; bool null_data; double * input; double * output; int * hidden_node_number; double *weight; double *hidden_node_output; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10)) { PG_RETURN_NULL(); } /* get weight_arg args */ weight_arg = PG_GETARG_ARRAYTYPE_P(0); null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count); if (null_data) { PG_RETURN_NULL(); } columns_arg = PG_GETARG_ARRAYTYPE_P(1); null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count); if (null_data) { PG_RETURN_NULL(); } /* get input_range_arg args */ input_range_arg = PG_GETARG_ARRAYTYPE_P(2); null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count); if (null_data) { PG_RETURN_NULL(); } /* get input_base_arg args */ input_base_arg = PG_GETARG_ARRAYTYPE_P(3); null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count); if (null_data) { PG_RETURN_NULL(); } /* get hidden_node_number_arg args */ hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4); null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count); if (null_data) { PG_RETURN_NULL(); } hidden_layer_number_arg= PG_GETARG_INT32(5); output_range_arg = PG_GETARG_FLOAT8(6); output_base_arg = PG_GETARG_FLOAT8(7); output_node_no_arg = PG_GETARG_INT32(8); normalize_arg = PG_GETARG_BOOL(9); numerical_label_arg = PG_GETARG_BOOL(10); #ifdef ALPINE_DEBUG elog(WARNING,"%f",DatumGetFloat8(columns_data[0])); #endif input = (double*)palloc(columns_count * sizeof(double));; output = (double*)palloc(output_node_no_arg * sizeof(double)); hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int)); weight = (double*)palloc(weight_count * sizeof(double)); for (i = 0; i < weight_count; i++) { weight[i] = DatumGetFloat8(weight_data[i]); } all_hidden_node_count = 0; for (i = 0; i < hidden_layer_number_arg; i++) { hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]); all_hidden_node_count += hidden_node_number[i]; } hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double)); /* get output array element type */ result_eltype = FLOAT8OID; get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign); /* construct result array */ result_count = output_node_no_arg; result_data = (Datum *)palloc(result_count * sizeof(Datum)); result_nulls = (bool *)palloc(result_count * sizeof(bool)); for (i = 0; i < result_count; i++) { result_nulls[i] = false; } //caculate input if (normalize_arg) { i = 0; while (i < columns_count) { if (DatumGetFloat8(input_range_data[i]) != 0) { input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i])); } else { input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i])); } #ifdef ALPINE_DEBUG elog(WARNING, "input:%f", input[i]); #endif i = i + 1; } } else { i = 0; while (i < columns_count) { input[i] = DatumGetFloat8(columns_data[i]); i = i + 1; } } // caculate hidden node output of 1st layer i = 0; while (i < hidden_node_number[0]) { hidden_node_output[i] = weight[0+i*(columns_count + 1)]; j = 0; while (j < columns_count) { hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j + i *(columns_count + 1)]; #ifdef ALPINE_DEBUG elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]); #endif j = j + 1; } if (hidden_node_output[i] < -45.0) { hidden_node_output[i] = 0; } else if (hidden_node_output[i] > 45.0) { hidden_node_output[i] = 1; } else { hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i]))); } #ifdef ALPINE_DEBUG elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]); #endif i = i + 1; } // calculate hidden layer 2~last output weight_index = hidden_node_number[0] * (columns_count + 1) ; if (hidden_layer_number_arg > 1) { hidden_node_number_index = 0; i = 1; while (i < hidden_layer_number_arg ) { hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1]; j = 0; while (j < hidden_node_number[i]) { hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j]; k = 0; while (k < hidden_node_number[i - 1]) { hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1]; k = k + 1; } if (hidden_node_output[hidden_node_number_index + j] < -45.0) { hidden_node_output[hidden_node_number_index + j] = 0; } else if (hidden_node_output[hidden_node_number_index + j] > 45.0) { hidden_node_output[hidden_node_number_index + j] = 1; } else { hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j]))); } j = j + 1; } weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1); i = i + 1; } } //compute output value of output node; i = 0; while (i < output_node_no_arg) { output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i]; #ifdef ALPINE_DEBUG elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]); #endif j = 0; while (j < hidden_node_number[hidden_layer_number_arg-1]) { #ifdef ALPINE_DEBUG elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]); #endif output[i] = output[i]+hidden_node_output[hidden_node_number_index + j] * weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]; j = j + 1; } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum[%d] %f", i, output[i]); #endif if (numerical_label_arg) { output[i] = ((output[i]) * output_range_arg+output_base_arg); #ifdef ALPINE_DEBUG elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg); #endif } else { if (output[i] < -45.0) { output[i] = 0; } else if (output[i] > 45.0) { output[i] = 1; } else { output[i] = (1.0/(1+exp(-1.0*output[i]))); } } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum2[%d] %f", i, output[i]); #endif i = i + 1; } ndims = 1; dims = (int *) palloc(sizeof(int)); dims[0] = result_count; lbs = (int *) palloc(sizeof(int)); lbs[0] = 1; for (i = 0; i < output_node_no_arg; i++) { result_data[i] = Float8GetDatum(output[i]); #ifdef ALPINE_DEBUG elog(WARNING,"output[%d]:%f",i, output[i]); #endif } result = construct_md_array((void *)result_data, result_nulls, ndims, dims, lbs, result_eltype, result_typlen, result_typbyval, result_typalign); // pfree(result); pfree(weight_data); pfree(columns_data); pfree(input_range_data); pfree(input_base_data); pfree(hidden_node_number_data); pfree(result_data); pfree(weight_nulls); pfree(columns_nulls); pfree(input_range_nulls); pfree(input_base_nulls); pfree(hidden_node_number_nulls); pfree(result_nulls); pfree(input); pfree(output); pfree(lbs); pfree(dims); pfree(hidden_node_output); pfree(weight); pfree(hidden_node_number); PG_RETURN_ARRAYTYPE_P(result); }
/*----------------------------------------------------------------------------- * array_cat : * concatenate two nD arrays to form an nD array, or * push an (n-1)D array onto the end of an nD array *---------------------------------------------------------------------------- */ Datum array_cat(PG_FUNCTION_ARGS) { ArrayType *v1, *v2; ArrayType *result; int *dims, *lbs, ndims, nitems, ndatabytes, nbytes; int *dims1, *lbs1, ndims1, nitems1, ndatabytes1; int *dims2, *lbs2, ndims2, nitems2, ndatabytes2; int i; char *dat1, *dat2; bits8 *bitmap1, *bitmap2; Oid element_type; Oid element_type1; Oid element_type2; int32 dataoffset; /* Concatenating a null array is a no-op, just return the other input */ if (PG_ARGISNULL(0)) { if (PG_ARGISNULL(1)) PG_RETURN_NULL(); result = PG_GETARG_ARRAYTYPE_P(1); PG_RETURN_ARRAYTYPE_P(result); } if (PG_ARGISNULL(1)) { result = PG_GETARG_ARRAYTYPE_P(0); PG_RETURN_ARRAYTYPE_P(result); } v1 = PG_GETARG_ARRAYTYPE_P(0); v2 = PG_GETARG_ARRAYTYPE_P(1); element_type1 = ARR_ELEMTYPE(v1); element_type2 = ARR_ELEMTYPE(v2); /* Check we have matching element types */ if (element_type1 != element_type2) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with element types %s and %s are not " "compatible for concatenation.", format_type_be(element_type1), format_type_be(element_type2)))); /* OK, use it */ element_type = element_type1; /*---------- * We must have one of the following combinations of inputs: * 1) one empty array, and one non-empty array * 2) both arrays empty * 3) two arrays with ndims1 == ndims2 * 4) ndims1 == ndims2 - 1 * 5) ndims1 == ndims2 + 1 *---------- */ ndims1 = ARR_NDIM(v1); ndims2 = ARR_NDIM(v2); /* * short circuit - if one input array is empty, and the other is not, we * return the non-empty one as the result * * if both are empty, return the first one */ if (ndims1 == 0 && ndims2 > 0) PG_RETURN_ARRAYTYPE_P(v2); if (ndims2 == 0) PG_RETURN_ARRAYTYPE_P(v1); /* the rest fall under rule 3, 4, or 5 */ if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays of %d and %d dimensions are not " "compatible for concatenation.", ndims1, ndims2))); /* get argument array details */ lbs1 = ARR_LBOUND(v1); lbs2 = ARR_LBOUND(v2); dims1 = ARR_DIMS(v1); dims2 = ARR_DIMS(v2); dat1 = ARR_DATA_PTR(v1); dat2 = ARR_DATA_PTR(v2); bitmap1 = ARR_NULLBITMAP(v1); bitmap2 = ARR_NULLBITMAP(v2); nitems1 = ArrayGetNItems(ndims1, dims1); nitems2 = ArrayGetNItems(ndims2, dims2); ndatabytes1 = ARR_SIZE(v1) - ARR_DATA_OFFSET(v1); ndatabytes2 = ARR_SIZE(v2) - ARR_DATA_OFFSET(v2); if (ndims1 == ndims2) { /* * resulting array is made up of the elements (possibly arrays * themselves) of the input argument arrays */ ndims = ndims1; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); dims[0] = dims1[0] + dims2[0]; lbs[0] = lbs1[0]; for (i = 1; i < ndims; i++) { if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing element dimensions are " "not compatible for concatenation."))); dims[i] = dims1[i]; lbs[i] = lbs1[i]; } } else if (ndims1 == ndims2 - 1) { /* * resulting array has the second argument as the outer array, with * the first argument inserted at the front of the outer dimension */ ndims = ndims2; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); memcpy(dims, dims2, ndims * sizeof(int)); memcpy(lbs, lbs2, ndims * sizeof(int)); /* increment number of elements in outer array */ dims[0] += 1; /* make sure the added element matches our existing elements */ for (i = 0; i < ndims1; i++) { if (dims1[i] != dims[i + 1] || lbs1[i] != lbs[i + 1]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing dimensions are not " "compatible for concatenation."))); } } else { /* * (ndims1 == ndims2 + 1) * * resulting array has the first argument as the outer array, with the * second argument appended to the end of the outer dimension */ ndims = ndims1; dims = (int *) palloc(ndims * sizeof(int)); lbs = (int *) palloc(ndims * sizeof(int)); memcpy(dims, dims1, ndims * sizeof(int)); memcpy(lbs, lbs1, ndims * sizeof(int)); /* increment number of elements in outer array */ dims[0] += 1; /* make sure the added element matches our existing elements */ for (i = 0; i < ndims2; i++) { if (dims2[i] != dims[i + 1] || lbs2[i] != lbs[i + 1]) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("cannot concatenate incompatible arrays"), errdetail("Arrays with differing dimensions are not " "compatible for concatenation."))); } } /* Do this mainly for overflow checking */ nitems = ArrayGetNItems(ndims, dims); /* build the result array */ ndatabytes = ndatabytes1 + ndatabytes2; if (ARR_HASNULL(v1) || ARR_HASNULL(v2)) { dataoffset = ARR_OVERHEAD_WITHNULLS(ndims, nitems); nbytes = ndatabytes + dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nbytes = ndatabytes + ARR_OVERHEAD_NONULLS(ndims); } result = (ArrayType *) palloc(nbytes); result->size = nbytes; result->ndim = ndims; result->dataoffset = dataoffset; result->elemtype = element_type; memcpy(ARR_DIMS(result), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int)); /* data area is arg1 then arg2 */ memcpy(ARR_DATA_PTR(result), dat1, ndatabytes1); memcpy(ARR_DATA_PTR(result) + ndatabytes1, dat2, ndatabytes2); /* handle the null bitmap if needed */ if (ARR_HASNULL(result)) { array_bitmap_copy(ARR_NULLBITMAP(result), 0, bitmap1, 0, nitems1); array_bitmap_copy(ARR_NULLBITMAP(result), nitems1, bitmap2, 0, nitems2); } PG_RETURN_ARRAYTYPE_P(result); }
Datum alpine_miner_nn_ca_change(PG_FUNCTION_ARGS) { ArrayType *weight_arg, *columns_arg, *input_range_arg, *input_base_arg,*hidden_node_number_arg, *result; Datum *weight_data, *columns_data, *input_range_data, *input_base_data, *hidden_node_number_data, *result_data; bool *weight_nulls, *columns_nulls, *input_range_nulls, *input_base_nulls, *hidden_node_number_nulls,*result_nulls; int weight_count, columns_count, input_range_count, input_base_count, hidden_node_number_count,result_count ; Oid result_eltype; int16 result_typlen; bool result_typbyval; char result_typalign; double output_range_arg,output_base_arg, learning_rate_ar, label_arg; int hidden_layer_number_arg, output_node_no_arg, set_size_arg; bool normalize_arg, numerical_label_arg ; int ndims, *dims, *lbs; int i; int j; int k; int all_hidden_node_count; int weight_index; int hidden_node_number_index = 0; bool null_data; double * input; double * output; int * hidden_node_number; double *weight; double *hidden_node_output; double delta = 0.0; double total_error = 0.0; double * output_error; double direct_output_error = 0.0; double * hidden_node_error; double error_sum = 0.0; double current_change = 0.0; double threshold_change = 0.0; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) || PG_ARGISNULL(6) || PG_ARGISNULL(7) || PG_ARGISNULL(8) || PG_ARGISNULL(9) || PG_ARGISNULL(10) || PG_ARGISNULL(11) || PG_ARGISNULL(12)){ PG_RETURN_NULL(); } /* get weight_arg args */ weight_arg = PG_GETARG_ARRAYTYPE_P(0); null_data = alpine_miner_deconstruct_array(weight_arg, &weight_data, &weight_nulls,&weight_count); if (null_data) { PG_RETURN_NULL(); } columns_arg = PG_GETARG_ARRAYTYPE_P(1); null_data = alpine_miner_deconstruct_array(columns_arg, &columns_data, &columns_nulls,&columns_count); if (null_data) { PG_RETURN_NULL(); } /* get input_range_arg args */ input_range_arg = PG_GETARG_ARRAYTYPE_P(2); null_data = alpine_miner_deconstruct_array(input_range_arg, &input_range_data, &input_range_nulls,&input_range_count); if (null_data) { PG_RETURN_NULL(); } /* get input_base_arg args */ input_base_arg = PG_GETARG_ARRAYTYPE_P(3); null_data = alpine_miner_deconstruct_array(input_base_arg, &input_base_data, &input_base_nulls,&input_base_count); if (null_data) { PG_RETURN_NULL(); } /* get hidden_node_number_arg args */ hidden_node_number_arg = PG_GETARG_ARRAYTYPE_P(4); null_data = alpine_miner_deconstruct_array(hidden_node_number_arg, &hidden_node_number_data, &hidden_node_number_nulls,&hidden_node_number_count); if (null_data) { PG_RETURN_NULL(); } hidden_layer_number_arg= PG_GETARG_INT32(5); output_range_arg = PG_GETARG_FLOAT8(6); output_base_arg = PG_GETARG_FLOAT8(7); output_node_no_arg = PG_GETARG_INT32(8); normalize_arg = PG_GETARG_BOOL(9); numerical_label_arg = PG_GETARG_BOOL(10); label_arg = PG_GETARG_FLOAT8(11); set_size_arg = PG_GETARG_INT32(12); if (set_size_arg <= 0) { set_size_arg = 1; } #ifdef ALPINE_DEBUG elog(WARNING,"%f",DatumGetFloat8(columns_data[0])); #endif input = (double*)palloc(columns_count * sizeof(double));; output = (double*)palloc(output_node_no_arg * sizeof(double)); hidden_node_number = (int*) palloc(hidden_node_number_count * sizeof(int)); weight = (double*)palloc(weight_count * sizeof(double)); for (i = 0; i < weight_count; i++) { weight[i] = DatumGetFloat8(weight_data[i]); } all_hidden_node_count = 0; for (i = 0; i < hidden_layer_number_arg; i++) { hidden_node_number[i] = DatumGetInt32(hidden_node_number_data[i]); all_hidden_node_count += hidden_node_number[i]; } hidden_node_output = (double*)palloc(all_hidden_node_count * sizeof(double)); //caculate input if (normalize_arg) { i = 0; while (i < columns_count) { if (DatumGetFloat8(input_range_data[i]) != 0) { input[i] = ((DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i]))/DatumGetFloat8(input_range_data[i])); } else { input[i] = (DatumGetFloat8(columns_data[i])-DatumGetFloat8(input_base_data[i])); } #ifdef ALPINE_DEBUG elog(WARNING, "input:%f", input[i]); #endif i = i + 1; } } else { i = 0; while (i < columns_count) { input[i] = DatumGetFloat8(columns_data[i]); i = i + 1; } } // caculate hidden node output of 1st layer i = 0; while (i < hidden_node_number[0]) { hidden_node_output[i] = weight[0+i*(columns_count + 1)]; j = 0; while (j < columns_count) { hidden_node_output[i] = hidden_node_output[i]+input[j]*weight[1 + j + i *(columns_count + 1)]; #ifdef ALPINE_DEBUG elog(WARNING,"hiddensum[%d] input[%d] %f weight[%d] %f", i, j,input[j] , 1+j +(i)*(columns_count +1), weight[1+j +i*(columns_count + 1)]); #endif j = j + 1; } if (hidden_node_output[i] < -45.0) { hidden_node_output[i] = 0; } else if (hidden_node_output[i] > 45.0) { hidden_node_output[i] = 1; } else { hidden_node_output[i] = (1.0/(1.0+exp( -1.0 * hidden_node_output[i]))); } #ifdef ALPINE_DEBUG elog(WARNING,"hidden[%d] %f", i, hidden_node_output[i]); #endif i = i + 1; } // calculate hidden layer 2~last output weight_index = hidden_node_number[0] * (columns_count + 1) ; if (hidden_layer_number_arg > 1) { hidden_node_number_index = 0; i = 1; while (i < hidden_layer_number_arg ) { hidden_node_number_index = hidden_node_number_index + hidden_node_number[i - 1]; j = 0; while (j < hidden_node_number[i]) { hidden_node_output[hidden_node_number_index + j] = weight[weight_index + (hidden_node_number[i - 1] +1) * j]; k = 0; while (k < hidden_node_number[i - 1]) { hidden_node_output[hidden_node_number_index + j] = hidden_node_output[hidden_node_number_index + j]+hidden_node_output[hidden_node_number_index - hidden_node_number[i - 1] + k]*weight[weight_index + (hidden_node_number[i - 1] +1) * j + k + 1]; k = k + 1; } if (hidden_node_output[hidden_node_number_index + j] < -45.0) { hidden_node_output[hidden_node_number_index + j] = 0; } else if (hidden_node_output[hidden_node_number_index + j] > 45.0) { hidden_node_output[hidden_node_number_index + j] = 1; } else { hidden_node_output[hidden_node_number_index + j] = (1.0/(1+exp(-1.0*hidden_node_output[hidden_node_number_index+j]))); } j = j + 1; } weight_index = weight_index + hidden_node_number[i] * (hidden_node_number[i - 1] + 1); i = i + 1; } } //compute output value of output node; i = 0; while (i < output_node_no_arg) { output[i] = weight[weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i]; #ifdef ALPINE_DEBUG elog(WARNING,"weightindex:%d,weight[%d] %f",weight_index, weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i, output[i]); #endif j = 0; while (j < hidden_node_number[hidden_layer_number_arg-1]) { #ifdef ALPINE_DEBUG elog(WARNING,"ouput[%d]:%f ,hidden_node_number_index:%d,j:%d, weight[%d]:%f",i,output[i], hidden_node_number_index ,j,1+j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i , weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]); #endif output[i] = output[i]+hidden_node_output[hidden_node_number_index + j] * weight[1 + j + weight_index + (hidden_node_number[hidden_layer_number_arg-1]+1) * i ]; j = j + 1; } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum[%d] %f", i, output[i]); #endif if (numerical_label_arg) { output[i] = ((output[i]) * output_range_arg+output_base_arg); #ifdef ALPINE_DEBUG elog(WARNING,"output:%f, %f,%f",output[i],output_range_arg,output_base_arg); #endif } else { if (output[i] < -45.0) { output[i] = 0; } else if (output[i] > 45.0) { output[i] = 1; } else { output[i] = (1.0/(1+exp(-1.0*output[i]))); } } #ifdef ALPINE_DEBUG elog(WARNING,"ouputsum2[%d] %f", i, output[i]); #endif i = i + 1; } /* get output array element type */ result_eltype = FLOAT8OID; get_typlenbyvalalign(result_eltype, &result_typlen, &result_typbyval, &result_typalign); /* construct result array */ result_count = weight_count + 1; result_data = (Datum *)palloc(result_count * sizeof(Datum)); result_nulls = (bool *)palloc(result_count * sizeof(bool)); for (i = 0; i < result_count; i++) { result_nulls[i] = false; } //compute error of output node output_error = (double *)palloc(output_node_no_arg * sizeof(double)); for(i = 0; i < output_node_no_arg; i++) { if(numerical_label_arg) { if (output_range_arg == 0.0) { direct_output_error = 0.0; } else { direct_output_error = (label_arg - output[i])/output_range_arg; } output_error[i] = direct_output_error; } else { if (((int)label_arg) == i) { direct_output_error = 1.0 - output[i]; } else { direct_output_error = 0.0 - output[i]; } #ifdef ALPINE_DEBUG elog(WARNING,"label_arg :%f %d %d", label_arg, i, (((int)label_arg) == i)); #endif output_error[i] = direct_output_error * output[i] * (1- output[i]); } total_error += direct_output_error*direct_output_error; #ifdef ALPINE_DEBUG elog(WARNING,"output_error[%d] %f totalerror:%f", i, output_error[i], total_error); #endif } //compute hidden_node_error of last layer hidden_node---- hidden_node_error = (double*)palloc(all_hidden_node_count * sizeof(double)); weight_index = weight_count - output_node_no_arg*(hidden_node_number[hidden_layer_number_arg - 1] + 1) ; hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1]; for(i = 0; i < hidden_node_number[hidden_layer_number_arg - 1]; i++) { error_sum = 0.0; for(k = 0; k < output_node_no_arg; k++) { error_sum = error_sum+output_error[k]*weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1]; #ifdef ALPINE_DEBUG elog(WARNING,"output_error[%d]:%f,weight[%d]:%f",k,output_error[k],weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1, weight[weight_index + (hidden_node_number[hidden_layer_number_arg - 1] + 1)*k + i + 1]); #endif } hidden_node_error[hidden_node_number_index + i] = error_sum*hidden_node_output[hidden_node_number_index + i]*(1.0-hidden_node_output[hidden_node_number_index + i]); #ifdef ALPINE_DEBUG elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+i, hidden_node_error[hidden_node_number_index + i]); #endif } //compute hidden_node_error of 1 layer to the one before last layer hidden node if (hidden_layer_number_arg > 1) { weight_index = weight_index - (hidden_node_number[hidden_layer_number_arg - 2] + 1)*hidden_node_number[hidden_layer_number_arg - 1]; hidden_node_number_index = hidden_node_number_index - hidden_node_number[hidden_layer_number_arg - 2]; for(i = hidden_layer_number_arg - 2; i >= 0; i--) { for(j = 0; j < hidden_node_number[i]; j++) { error_sum = 0.0; for (k = 0; k < hidden_node_number[i + 1]; k++) { error_sum = error_sum+hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k]*weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1]; #ifdef ALPINE_DEBUG elog(WARNING,"i:%d j:%d k:%d; hidden_node_error[%d]:%f,weight[%d]:%f",i,j,k,hidden_node_number_index + hidden_node_number[i] + k, hidden_node_error[hidden_node_number_index + hidden_node_number[i] + k], weight_index + (hidden_node_number[i]+1)*(k) + j + 1,weight[weight_index + (hidden_node_number[i]+1)*(k) + j + 1]); #endif } hidden_node_error[hidden_node_number_index + j] = error_sum*hidden_node_output[hidden_node_number_index + j]*(1-hidden_node_output[hidden_node_number_index + j]); #ifdef ALPINE_DEBUG elog(WARNING,"hidden_node_error[%d] %f ", hidden_node_number_index+j, hidden_node_error[hidden_node_number_index + j]); #endif } weight_index = weight_index - (hidden_node_number[i - 1]+1) * hidden_node_number[i]; hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1]; } } //compute weight change of output node weight_index = weight_count - (hidden_node_number[hidden_layer_number_arg - 1]+ 1)* output_node_no_arg; hidden_node_number_index = all_hidden_node_count - hidden_node_number[hidden_layer_number_arg - 1]; for(i = 0; i < output_node_no_arg; i++) { delta = 1.0/set_size_arg*output_error[i]; threshold_change = delta; result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i)] = Float8GetDatum(threshold_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f ", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i), threshold_change); #endif for(j = 0; j < hidden_node_number[hidden_layer_number_arg - 1] ; j++) { current_change = delta * hidden_node_output[hidden_node_number_index + j]; result_data[weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1 +j] = Float8GetDatum(current_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f , i:%d j:%d output_error[%d]:%f, hidden_node_output[%d]:%f", weight_index +(hidden_node_number[hidden_layer_number_arg - 1]+ 1)*(i) + 1+ j, current_change, i,j,i,output_error[i],hidden_node_number_index + j, hidden_node_output[hidden_node_number_index + j]); #endif } } //compute weight change of hidden node last layer to 2 layer if (hidden_layer_number_arg > 1) { for(i = hidden_layer_number_arg - 1; i >= 1; i--) { weight_index = weight_index - (hidden_node_number[i - 1]+1)*hidden_node_number[i]; hidden_node_number_index = hidden_node_number_index - hidden_node_number[i - 1]; delta = 0.0; for (j = 0; j < hidden_node_number[i]; j++) { delta = (1.0/set_size_arg*hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j]); threshold_change = delta; result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j)] = Float8GetDatum(threshold_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f ", weight_index + (hidden_node_number[i - 1] + 1) * (j), threshold_change); #endif for(k = 0; k < hidden_node_number[i - 1]; k++) { current_change = delta * hidden_node_output[hidden_node_number_index + k]; result_data[weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 + k] = Float8GetDatum(current_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f i:%d, j:%d k:%d hidden_node_error[%d]:%f hidden_node_output[%d]:%f", weight_index + (hidden_node_number[i - 1] + 1) * (j) + 1 + k, current_change,i,j,k,hidden_node_number_index + hidden_node_number[i - 1] + j, hidden_node_error[hidden_node_number_index + hidden_node_number[i - 1] + j], hidden_node_number_index + k,hidden_node_output[hidden_node_number_index + k]); #endif } } } } //compute weight change of first layer hidden node weight_index = 0; hidden_node_number_index = 0; delta = 0.0; for(j = 0; j < hidden_node_number[0]; j++) { delta = 1.0/set_size_arg*hidden_node_error[hidden_node_number_index + j]; threshold_change = delta; result_data[weight_index + (columns_count+1)*(j)] = Float8GetDatum(threshold_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f ", weight_index + (columns_count+1)*(j), threshold_change); #endif for(k = 0; k < columns_count; k++) { current_change = delta*input[k]; result_data[weight_index + (columns_count+1)*(j) + k + 1] = Float8GetDatum(current_change); #ifdef ALPINE_DEBUG elog(WARNING, " result_data [%d] %f j:%d k:%d hidden_node_error[%d]:%f input[%d]:%f", weight_index + (columns_count+1)*(j) + k + 1, current_change,j,k,hidden_node_number_index + j, hidden_node_error[hidden_node_number_index + j], k, input[k]); #endif } } result_data[weight_count] = Float8GetDatum(total_error); ndims = 1; dims = (int *) palloc(sizeof(int)); dims[0] = result_count; lbs = (int *) palloc(sizeof(int)); lbs[0] = 1; result = construct_md_array((void *)result_data, result_nulls, ndims, dims, lbs, result_eltype, result_typlen, result_typbyval, result_typalign); // pfree(result); pfree(weight_data); pfree(columns_data); pfree(input_range_data); pfree(input_base_data); pfree(hidden_node_number_data); pfree(result_data); pfree(weight_nulls); pfree(columns_nulls); pfree(input_range_nulls); pfree(input_base_nulls); pfree(hidden_node_number_nulls); pfree(result_nulls); pfree(input); pfree(output); pfree(lbs); pfree(dims); pfree(hidden_node_output); pfree(weight); pfree(hidden_node_number); pfree(hidden_node_error); pfree(output_error); PG_RETURN_ARRAYTYPE_P(result); }
Datum alpine_miner_lr_combine(PG_FUNCTION_ARGS) { ArrayType *state1, *state2, *result; float8 *state1Data, *state2Data, *resultData; int i, size; int statelen; if (PG_ARGISNULL(0)) { if (PG_ARGISNULL(1)) PG_RETURN_NULL(); PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(1)); } if (PG_ARGISNULL(1)) PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P(0)); state1 = PG_GETARG_ARRAYTYPE_P(0); state2 = PG_GETARG_ARRAYTYPE_P(1); if (ARR_NULLBITMAP(state1) || ARR_NULLBITMAP(state2) || ARR_NDIM(state1) != 1 || ARR_NDIM(state2) != 1 || ARR_ELEMTYPE(state1) != FLOAT8OID || ARR_ELEMTYPE(state2) != FLOAT8OID) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("preliminary segment-level calculation function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); } if (ARR_DIMS(state1)[0] == 1) PG_RETURN_ARRAYTYPE_P(state2); if (ARR_DIMS(state2)[0] == 1) PG_RETURN_ARRAYTYPE_P(state1); state1Data = (float8*) ARR_DATA_PTR(state1); state2Data = (float8*) ARR_DATA_PTR(state2); if (ARR_DIMS(state1)[0] != ARR_DIMS(state2)[0]) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("preliminary segment-level calculation function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)), errdetail("The independent-variable array is not of constant width."))); } statelen = ARR_DIMS(state1)[0]; size = statelen * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); result = (ArrayType *) palloc(size); SET_VARSIZE(result, size); result->ndim = 1; result->dataoffset = 0; result->elemtype = FLOAT8OID; ARR_DIMS(result)[0] = statelen; ARR_LBOUND(result)[0] = 1; resultData = (float8*) ARR_DATA_PTR(result); memset(resultData, 0, statelen * sizeof(float8)); for (i = 0; i < statelen; i++){ resultData[i] = state1Data[i] + state2Data[i]; } PG_RETURN_ARRAYTYPE_P(result); }
Datum hstore_from_arrays(PG_FUNCTION_ARGS) { int4 buflen; HStore *out; Pairs *pairs; Datum *key_datums; bool *key_nulls; int key_count; Datum *value_datums; bool *value_nulls; int value_count; ArrayType *key_array; ArrayType *value_array; int i; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); key_array = PG_GETARG_ARRAYTYPE_P(0); Assert(ARR_ELEMTYPE(key_array) == TEXTOID); /* * must check >1 rather than != 1 because empty arrays have 0 dimensions, * not 1 */ if (ARR_NDIM(key_array) > 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); deconstruct_array(key_array, TEXTOID, -1, false, 'i', &key_datums, &key_nulls, &key_count); /* value_array might be NULL */ if (PG_ARGISNULL(1)) { value_array = NULL; value_count = key_count; value_datums = NULL; value_nulls = NULL; } else { value_array = PG_GETARG_ARRAYTYPE_P(1); Assert(ARR_ELEMTYPE(value_array) == TEXTOID); if (ARR_NDIM(value_array) > 1) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("wrong number of array subscripts"))); if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) && (ARR_NDIM(key_array) != ARR_NDIM(value_array) || ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] || ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0])) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("arrays must have same bounds"))); deconstruct_array(value_array, TEXTOID, -1, false, 'i', &value_datums, &value_nulls, &value_count); Assert(key_count == value_count); } pairs = palloc(key_count * sizeof(Pairs)); for (i = 0; i < key_count; ++i) { if (key_nulls[i]) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed for hstore key"))); if (!value_nulls || value_nulls[i]) { pairs[i].key = VARDATA_ANY(key_datums[i]); pairs[i].val = NULL; pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i])); pairs[i].vallen = 4; pairs[i].isnull = true; pairs[i].needfree = false; } else { pairs[i].key = VARDATA_ANY(key_datums[i]); pairs[i].val = VARDATA_ANY(value_datums[i]); pairs[i].keylen = hstoreCheckKeyLen(VARSIZE_ANY_EXHDR(key_datums[i])); pairs[i].vallen = hstoreCheckValLen(VARSIZE_ANY_EXHDR(value_datums[i])); pairs[i].isnull = false; pairs[i].needfree = false; } } key_count = hstoreUniquePairs(pairs, key_count, &buflen); out = hstorePairs(pairs, key_count, buflen); PG_RETURN_POINTER(out); }
/* * Common subroutine for num_nulls() and num_nonnulls(). * Returns TRUE if successful, FALSE if function should return NULL. * If successful, total argument count and number of nulls are * returned into *nargs and *nulls. */ static bool count_nulls(FunctionCallInfo fcinfo, int32 *nargs, int32 *nulls) { int32 count = 0; int i; /* Did we get a VARIADIC array argument, or separate arguments? */ if (get_fn_expr_variadic(fcinfo->flinfo)) { ArrayType *arr; int ndims, nitems, *dims; bits8 *bitmap; Assert(PG_NARGS() == 1); /* * If we get a null as VARIADIC array argument, we can't say anything * useful about the number of elements, so return NULL. This behavior * is consistent with other variadic functions - see concat_internal. */ if (PG_ARGISNULL(0)) return false; /* * Non-null argument had better be an array. We assume that any call * context that could let get_fn_expr_variadic return true will have * checked that a VARIADIC-labeled parameter actually is an array. So * it should be okay to just Assert that it's an array rather than * doing a full-fledged error check. */ Assert(OidIsValid(get_base_element_type(get_fn_expr_argtype(fcinfo->flinfo, 0)))); /* OK, safe to fetch the array value */ arr = PG_GETARG_ARRAYTYPE_P(0); /* Count the array elements */ ndims = ARR_NDIM(arr); dims = ARR_DIMS(arr); nitems = ArrayGetNItems(ndims, dims); /* Count those that are NULL */ bitmap = ARR_NULLBITMAP(arr); if (bitmap) { int bitmask = 1; for (i = 0; i < nitems; i++) { if ((*bitmap & bitmask) == 0) count++; bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } *nargs = nitems; *nulls = count; } else { /* Separate arguments, so just count 'em */ for (i = 0; i < PG_NARGS(); i++) { if (PG_ARGISNULL(i)) count++; } *nargs = PG_NARGS(); *nulls = count; } return true; }
/* * array_position_common * Common code for array_position and array_position_start * * These are separate wrappers for the sake of opr_sanity regression test. * They are not strict so we have to test for null inputs explicitly. */ static Datum array_position_common(FunctionCallInfo fcinfo) { ArrayType *array; Oid collation = PG_GET_COLLATION(); Oid element_type; Datum searched_element, value; bool isnull; int position, position_min; bool found = false; TypeCacheEntry *typentry; ArrayMetaState *my_extra; bool null_search; ArrayIterator array_iterator; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); array = PG_GETARG_ARRAYTYPE_P(0); element_type = ARR_ELEMTYPE(array); /* * We refuse to search for elements in multi-dimensional arrays, since we * have no good way to report the element's location in the array. */ if (ARR_NDIM(array) > 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("searching for elements in multidimensional arrays is not supported"))); if (PG_ARGISNULL(1)) { /* fast return when the array doesn't have nulls */ if (!array_contains_nulls(array)) PG_RETURN_NULL(); searched_element = (Datum) 0; null_search = true; } else { searched_element = PG_GETARG_DATUM(1); null_search = false; } position = (ARR_LBOUND(array))[0] - 1; /* figure out where to start */ if (PG_NARGS() == 3) { if (PG_ARGISNULL(2)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("initial position must not be null"))); position_min = PG_GETARG_INT32(2); } else position_min = (ARR_LBOUND(array))[0]; /* * We arrange to look up type info for array_create_iterator only once per * series of calls, assuming the element type doesn't change underneath * us. */ my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = ~element_type; } if (my_extra->element_type != element_type) { get_typlenbyvalalign(element_type, &my_extra->typlen, &my_extra->typbyval, &my_extra->typalign); typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO); if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify an equality operator for type %s", format_type_be(element_type)))); my_extra->element_type = element_type; fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc, fcinfo->flinfo->fn_mcxt); } /* Examine each array element until we find a match. */ array_iterator = array_create_iterator(array, 0, my_extra); while (array_iterate(array_iterator, &value, &isnull)) { position++; /* skip initial elements if caller requested so */ if (position < position_min) continue; /* * Can't look at the array element's value if it's null; but if we * search for null, we have a hit and are done. */ if (isnull || null_search) { if (isnull && null_search) { found = true; break; } else continue; } /* not nulls, so run the operator */ if (DatumGetBool(FunctionCall2Coll(&my_extra->proc, collation, searched_element, value))) { found = true; break; } } array_free_iterator(array_iterator); /* Avoid leaking memory when handed toasted input */ PG_FREE_IF_COPY(array, 0); if (!found) PG_RETURN_NULL(); PG_RETURN_INT32(position); }