inline AbstractionLayer::MutableArrayHandle<T> AbstractionLayer::Allocator::allocateArray(size_t inNumElements) const { /* * Check that the size will not exceed addressable memory. Therefore, the * following precondition has to hold: * ((std::numeric_limits<size_t>::max() - ARR_OVERHEAD_NONULLS(1)) / * inElementSize >= inNumElements) */ if ((std::numeric_limits<size_t>::max() - ARR_OVERHEAD_NONULLS(1)) / sizeof(T) < inNumElements) throw std::bad_alloc(); size_t size = sizeof(T) * inNumElements + ARR_OVERHEAD_NONULLS(1); ArrayType *array; // Note: Except for the allocate call, the following statements do not call // into the PostgreSQL backend. We are only using macros here. // PostgreSQL requires that all memory is overwritten with zeros. So // we ingore ZM here array = static_cast<ArrayType*>(allocate<MC, dbal::DoZero, F>(size)); SET_VARSIZE(array, size); array->ndim = 1; array->dataoffset = 0; array->elemtype = TypeTraits<T>::oid; ARR_DIMS(array)[0] = inNumElements; ARR_LBOUND(array)[0] = 1; return MutableArrayHandle<T>(array); }
/* Create a new int array with room for "num" elements */ ArrayType * new_intArrayType(int num) { ArrayType *r; int nbytes; /* if no elements, return a zero-dimensional array */ if (num <= 0) { r = construct_empty_array(INT4OID); return r; } nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num; r = (ArrayType *) palloc0(nbytes); SET_VARSIZE(r, nbytes); ARR_NDIM(r) = 1; r->dataoffset = 0; /* marker for no null bitmap */ ARR_ELEMTYPE(r) = INT4OID; ARR_DIMS(r)[0] = num; ARR_LBOUND(r)[0] = 1; return r; }
static ArrayType * intArrayInit(int ndims, int const * dims, int const * lbs) { ArrayType * res; int size; int nbytes; if (ndims < 0) /* we do allow zero-dimension arrays */ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number of dimensions: %d", ndims))); if (ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndims, MAXDIM))); /* fast track for empty array */ if (ndims == 0) return construct_empty_array(INT4OID); size = ArrayGetNItems(ndims, dims); nbytes = ARR_OVERHEAD_NONULLS(ndims); nbytes += size * 4; res = palloc0(nbytes); SET_VARSIZE(res, nbytes); res->ndim = ndims; res->elemtype = INT4OID; res->dataoffset = 0; memcpy(ARR_DIMS(res), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(res), lbs, ndims * sizeof(int)); return res; }
ArrayType* createArrayType(jsize nElems, size_t elemSize, Oid elemType, bool withNulls) { ArrayType* v; Size nBytes = elemSize * nElems; MemoryContext currCtx = Invocation_switchToUpperContext(); Size dataoffset; if(withNulls) { dataoffset = ARR_OVERHEAD_WITHNULLS(1, nElems); nBytes += dataoffset; } else { dataoffset = 0; /* marker for no null bitmap */ nBytes += ARR_OVERHEAD_NONULLS(1); } v = (ArrayType*)palloc0(nBytes); AssertVariableIsOfType(v->dataoffset, int32); v->dataoffset = (int32)dataoffset; MemoryContextSwitchTo(currCtx); SET_VARSIZE(v, nBytes); ARR_NDIM(v) = 1; ARR_ELEMTYPE(v) = elemType; *((int*)ARR_DIMS(v)) = nElems; *((int*)ARR_LBOUND(v)) = 1; return v; }
/* * get_flat_size method for expanded arrays */ static Size EA_get_flat_size(ExpandedObjectHeader *eohptr) { ExpandedArrayHeader *eah = (ExpandedArrayHeader *) eohptr; int nelems; int ndims; Datum *dvalues; bool *dnulls; Size nbytes; int i; Assert(eah->ea_magic == EA_MAGIC); /* Easy if we have a valid flattened value */ if (eah->fvalue) return ARR_SIZE(eah->fvalue); /* If we have a cached size value, believe that */ if (eah->flat_size) return eah->flat_size; /* * Compute space needed by examining dvalues/dnulls. Note that the result * array will have a nulls bitmap if dnulls isn't NULL, even if the array * doesn't actually contain any nulls now. */ nelems = eah->nelems; ndims = eah->ndims; Assert(nelems == ArrayGetNItems(ndims, eah->dims)); dvalues = eah->dvalues; dnulls = eah->dnulls; nbytes = 0; for (i = 0; i < nelems; i++) { if (dnulls && dnulls[i]) continue; nbytes = att_addlength_datum(nbytes, eah->typlen, dvalues[i]); nbytes = att_align_nominal(nbytes, eah->typalign); /* check for overflow of total request */ if (!AllocSizeIsValid(nbytes)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("array size exceeds the maximum allowed (%d)", (int) MaxAllocSize))); } if (dnulls) nbytes += ARR_OVERHEAD_WITHNULLS(ndims, nelems); else nbytes += ARR_OVERHEAD_NONULLS(ndims); /* cache for next time */ eah->flat_size = nbytes; return nbytes; }
Datum alpine_miner_lr_ca_derivative(PG_FUNCTION_ARGS) { ArrayType *beta_arg, *columns_arg, *result; float8 *beta_data, *columns_data, *result_data; int beta_count, columns_count, result_count; bool add_intercept_arg; double weight_arg; int y_arg; int size; 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; 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_derivative(columns_count,columns_data, result_data ,weight_arg, y_arg, add_intercept_arg, pi); PG_RETURN_ARRAYTYPE_P(result); }
inline MutableArrayHandle<T> Allocator::internalAllocateArray( const std::array<std::size_t, Dimensions>& inNumElements) const { std::size_t numElements = Dimensions ? 1 : 0; for (std::size_t i = 0; i < Dimensions; ++i) numElements *= inNumElements[i]; /* * Check that the size will not exceed addressable memory. Therefore, the * following precondition has to hold: * ((std::numeric_limits<std::size_t>::max() * - ARR_OVERHEAD_NONULLS(Dimensions)) / inElementSize >= numElements) */ if ((std::numeric_limits<std::size_t>::max() - ARR_OVERHEAD_NONULLS(Dimensions)) / sizeof(T) < numElements) throw std::bad_alloc(); std::size_t size = sizeof(T) * numElements + ARR_OVERHEAD_NONULLS(Dimensions); ArrayType *array; // Note: Except for the allocate call, the following statements do not call // into the PostgreSQL backend. We are only using macros here. // PostgreSQL requires that all memory is overwritten with zeros. So // we ingore ZM here array = static_cast<ArrayType*>(allocate<MC, dbal::DoZero, F>(size)); SET_VARSIZE(array, size); array->ndim = Dimensions; array->dataoffset = 0; array->elemtype = TypeTraits<T>::oid; for (std::size_t i = 0; i < Dimensions; ++i) { ARR_DIMS(array)[i] = static_cast<int>(inNumElements[i]); ARR_LBOUND(array)[i] = 1; } return MutableArrayHandle<T>(array); }
Datum alpine_miner_covar_sam_accum(PG_FUNCTION_ARGS) { ArrayType *state; float8 * state_array_data; ArrayType * column_array; int column_size; float8 * column_array_data; int i; int k ; int j; if (PG_ARGISNULL(0)){ PG_RETURN_NULL(); } state = PG_GETARG_ARRAYTYPE_P(0); state_array_data = (float8*) ARR_DATA_PTR(state); column_array = PG_GETARG_ARRAYTYPE_P(1); column_size = ARR_DIMS(column_array)[0]; column_array_data = (float8*) ARR_DATA_PTR(column_array); if (ARR_DIMS(state)[0] == 1){ int result_size = column_size * ( column_size + 1)/2 + column_size+2; int size = result_size * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); state = (ArrayType *) palloc(size); SET_VARSIZE(state, size); state->ndim = 1; state->dataoffset = 0; state->elemtype = FLOAT8OID; ARR_DIMS(state)[0] = result_size; ARR_LBOUND(state)[0] = 1; state_array_data = (float8*) ARR_DATA_PTR(state); memset(state_array_data, 0, result_size * sizeof(float8)); } k = 0; for ( i = 0; i < column_size; i++){ for(j = i; j < column_size; j++){ state_array_data[k] += column_array_data[i] * column_array_data[j]; k++; } } for( i = 0; i < column_size; i++){ state_array_data[k + i] += column_array_data[i]; } state_array_data[k+i]++; state_array_data[k+i+1]=column_size; PG_RETURN_ARRAYTYPE_P(state); }
Datum alpine_miner_covar_sam_final(PG_FUNCTION_ARGS){ ArrayType *state ; ArrayType *result; float8 * resultData; float8 * state_array_data; int total_length; int column_size; float8 row_size; int result_size; int size; int k=0; int i,j; int sam_row_size; if (PG_ARGISNULL(0)) PG_RETURN_NULL(); state = PG_GETARG_ARRAYTYPE_P(0); state_array_data = (float8*) ARR_DATA_PTR(state); total_length=ARR_DIMS(state)[0]; column_size=state_array_data[total_length-1]; row_size=state_array_data[total_length-2]; result_size=column_size*(column_size+1)/2; size = result_size * 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_size; ARR_LBOUND(result)[0] = 1; resultData = (float8*) ARR_DATA_PTR(result); memset(resultData, 0, result_size * sizeof(float8)); sam_row_size=row_size-1; if(sam_row_size<=0) sam_row_size=1; k=0; for ( i = 0; i < column_size; i++){ for( j = i; j < column_size; j++){ resultData[k] =state_array_data[k]/sam_row_size- state_array_data[result_size+i] * state_array_data[result_size+j]/row_size/sam_row_size; k++; } } PG_RETURN_ARRAYTYPE_P(result); }
Datum internal_get_array_of_close_canopies(PG_FUNCTION_ARGS) { SvecType *svec; Datum *all_canopies; int num_all_canopies; float8 threshold; PGFunction metric_fn; ArrayType *close_canopies_arr; int4 *close_canopies; int num_close_canopies; size_t bytes; MemoryContext mem_context_for_function_calls; svec = PG_GETARG_SVECTYPE_P(verify_arg_nonnull(fcinfo, 0)); get_svec_array_elms(PG_GETARG_ARRAYTYPE_P(verify_arg_nonnull(fcinfo, 1)), &all_canopies, &num_all_canopies); threshold = PG_GETARG_FLOAT8(verify_arg_nonnull(fcinfo, 2)); metric_fn = get_metric_fn(PG_GETARG_INT32(verify_arg_nonnull(fcinfo, 3))); mem_context_for_function_calls = setup_mem_context_for_functional_calls(); close_canopies = (int4 *) palloc(sizeof(int4) * num_all_canopies); num_close_canopies = 0; for (int i = 0; i < num_all_canopies; i++) { if (compute_metric(metric_fn, mem_context_for_function_calls, PointerGetDatum(svec), all_canopies[i]) < threshold) close_canopies[num_close_canopies++] = i + 1 /* lower bound */; } MemoryContextDelete(mem_context_for_function_calls); /* If we cannot find any close canopy, return NULL. Note that the result * we return will be passed to internal_kmeans_closest_centroid() and if the * array of close canopies is NULL, then internal_kmeans_closest_centroid() * will consider and compute the distance to all centroids. */ if (num_close_canopies == 0) PG_RETURN_NULL(); bytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int4) * num_close_canopies; close_canopies_arr = (ArrayType *) palloc0(bytes); SET_VARSIZE(close_canopies_arr, bytes); ARR_ELEMTYPE(close_canopies_arr) = INT4OID; ARR_NDIM(close_canopies_arr) = 1; ARR_DIMS(close_canopies_arr)[0] = num_close_canopies; ARR_LBOUND(close_canopies_arr)[0] = 1; memcpy(ARR_DATA_PTR(close_canopies_arr), close_canopies, sizeof(int4) * num_close_canopies); PG_RETURN_ARRAYTYPE_P(close_canopies_arr); }
ArrayType * resize_intArrayType(ArrayType *a, int num) { int nbytes = ARR_OVERHEAD_NONULLS(NDIM) + sizeof(int) * num; if (num == ARRNELEMS(a)) return a; a = (ArrayType *) repalloc(a, nbytes); SET_VARSIZE(a, nbytes); *((int *) ARR_DIMS(a)) = num; return a; }
Datum alpine_plda_count_accum(PG_FUNCTION_ARGS) { ArrayType *state; int32 * state_array_data; ArrayType * column_array; ArrayType * assign_array; int32 column_size,assign_size,topicnumber,wordnumber; int32 result_size; int32 size; int32 * column_array_data; int32 * assign_array_data; int32 k; if (PG_ARGISNULL(0)){ PG_RETURN_NULL(); } state = PG_GETARG_ARRAYTYPE_P(0); state_array_data = (int32*) ARR_DATA_PTR(state); column_array = PG_GETARG_ARRAYTYPE_P(1); column_size = ARR_DIMS(column_array)[0]; column_array_data = (int32*) ARR_DATA_PTR(column_array); assign_array=PG_GETARG_ARRAYTYPE_P(2); assign_size = ARR_DIMS(assign_array)[0]; assign_array_data = (int32*) ARR_DATA_PTR(assign_array); topicnumber=PG_GETARG_INT32(3); wordnumber =PG_GETARG_INT32(4); if (ARR_DIMS(state)[0] == 1){ result_size = topicnumber*wordnumber; size = result_size * sizeof(int32) + ARR_OVERHEAD_NONULLS(1); state = (ArrayType *) palloc(size); SET_VARSIZE(state, size); state->ndim = 1; state->dataoffset = 0; state->elemtype = INT4OID; ARR_DIMS(state)[0] = result_size; ARR_LBOUND(state)[0] = 1; state_array_data = (int32*) ARR_DATA_PTR(state); memset(state_array_data, 0, result_size * sizeof(int32)); } for ( k = 0; k < column_size; k++){ state_array_data[topicnumber*(column_array_data[k]-1)+assign_array_data[k]-1]=state_array_data[topicnumber*(column_array_data[k]-1)+assign_array_data[k]-1]+1; } PG_RETURN_ARRAYTYPE_P(state); }
/* Create a new int array with room for "num" elements */ ArrayType * new_intArrayType(int num) { ArrayType *r; int nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num; r = (ArrayType *) palloc0(nbytes); SET_VARSIZE(r, nbytes); ARR_NDIM(r) = 1; r->dataoffset = 0; /* marker for no null bitmap */ ARR_ELEMTYPE(r) = INT4OID; ARR_DIMS(r)[0] = num; ARR_LBOUND(r)[0] = 1; return r; }
Datum domainname_parts(PG_FUNCTION_ARGS) { text *in = PG_GETARG_TEXT_P(0); const char *s = VARDATA(in); const char *b = s, *p = s, *e = s + VARSIZE_ANY_EXHDR(in); int nelems = 0; int nbytes = ARR_OVERHEAD_NONULLS(1); ArrayType *r; char *o; while (p < e) { b = p; STRSEARCH(p, e-p, *p == '.'); nelems ++; nbytes += VARHDRSZ + (p-b); nbytes = INTALIGN(nbytes); p ++; } r = (ArrayType *)palloc(nbytes); SET_VARSIZE(r, nbytes); r->ndim = 1; r->dataoffset = 0; r->elemtype = TEXTOID; *ARR_DIMS(r) = nelems; *ARR_LBOUND(r) = 1; p = s; o = ARR_DATA_PTR(r); while (p < e) { b = p; STRSEARCH(p, e-p, *p == '.'); SET_VARSIZE(o, VARHDRSZ+(p-b)); o = VARDATA(o); memcpy(o, b, p-b); o += INTALIGN(p-b); p ++; } PG_FREE_IF_COPY(in, 0); PG_RETURN_ARRAYTYPE_P(r); }
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 __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); }
/*----------------------------------------------------------------------------- * 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); SET_VARSIZE(result, 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 __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); }
/* * Preliminary segment-level calculation function for multi-linear regression * aggregates. */ Datum float8_mregr_combine(PG_FUNCTION_ARGS) { ArrayType *state1, *state2, *result; float8 *state1Data, *state2Data, *resultData; uint32 len; uint64 statelen, i; Size size; /* We should be strict, but it doesn't hurt to be paranoid */ 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); /* Ensure that both arrays are single dimensional float8[] arrays */ 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)))); } /* * Remember that we initialized to {0}, so if either array is still at * the initial value then just return the other one */ 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] || state1Data[0] != state2Data[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."))); } len = state1Data[0]; statelen = STATE_LEN(len); /* * Violation of any of the following conditions indicates bogus inputs. */ if (state1Data[0] > UINT32_MAX || (uint64) ARR_DIMS(state1)[0] != statelen || !IS_FEASIBLE_STATE_LEN(statelen)) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("preliminary segment-level calculation function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); } /* Validations pass, allocate memory for result and do work */ /* * Precondition: * IS_FEASIBLE_STATE_LEN(statelen) */ 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)); /* * Contents of 'state' are as follows: * [0] = len(X[]) * [1] = count * [2] = sum(y) * [3] = sum(y*y) * [4:N] = sum(X'[] * y) * [N+1:M] = sum(X[] * X'[]) * N = 3 + len(X) * M = N + len(X)*len(X) */ resultData[0] = len; for (i = 1; i < statelen; i++) resultData[i] = state1Data[i] + state2Data[i]; PG_RETURN_ARRAYTYPE_P(result); }
/* * 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)); }
static bool alpine_miner_float8_mregr_accum_get_state(PG_FUNCTION_ARGS, MRegrAccumState *outState) { float8 *stateData; int len, statelen; /* We should be strict, but it doesn't hurt to be paranoid */ if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2)) return false; outState->stateAsArray = PG_GETARG_ARRAYTYPE_P(0); outState->newX = PG_GETARG_ARRAYTYPE_P(2); /* Ensure that both arrays are single dimensional float8[] arrays */ if (ARR_NULLBITMAP(outState->stateAsArray) || ARR_NDIM(outState->stateAsArray) != 1 || ARR_ELEMTYPE(outState->stateAsArray) != FLOAT8OID || ARR_NDIM(outState->newX) != 1 || ARR_ELEMTYPE(outState->newX) != FLOAT8OID) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); /* Only callable as a transition function */ if (!(fcinfo->context && IsA(fcinfo->context, AggState))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" not called from aggregate", format_procedure(fcinfo->flinfo->fn_oid)))); /* newX with nulls will be ignored */ if (ARR_NULLBITMAP(outState->newX)) return false; /* * If length(state) == 1 then it is an unitialized state, extend as * needed, we use this instead of NULL so that we can declare the * function as strict. */ len = ARR_DIMS(outState->newX)[0]; statelen = 1 + (3*len + len*len)/2; if (ARR_DIMS(outState->stateAsArray)[0] == 1) { int size = statelen * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); outState->stateAsArray = (ArrayType *) palloc(size); SET_VARSIZE(outState->stateAsArray, size); outState->stateAsArray->ndim = 1; outState->stateAsArray->dataoffset = 0; outState->stateAsArray->elemtype = FLOAT8OID; ARR_DIMS(outState->stateAsArray)[0] = statelen; ARR_LBOUND(outState->stateAsArray)[0] = 1; stateData = (float8*) ARR_DATA_PTR(outState->stateAsArray); memset(stateData, 0, statelen * sizeof(float8)); stateData[0] = len; } /* * Contents of 'state' are as follows: * [0] = len(X[]) * [1] = count * [2] = sum(y) * [3] = sum(y*y) * [4:N] = sum(X'[] * y) * [N+1:M] = sum(X[] * X'[]) * N = 3 + len(X) * M = N + len(X)*len(X) */ outState->len = (float8*) ARR_DATA_PTR(outState->stateAsArray); outState->Xty = outState->len + 1; outState->XtX = outState->len + 1 + len; outState->newXData = (float8*) ARR_DATA_PTR(outState->newX); /* It is an error if the number of indepent variables is not constant */ if (*outState->len != len) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)), errdetail("The independent-variable array is not of constant width."))); } /* Something is seriously fishy if our state has the wrong length */ if (ARR_DIMS(outState->stateAsArray)[0] != statelen) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); } /* Okay... All's good now do the work */ return true; }
static bool float8_mregr_accum_get_args(FunctionCallInfo fcinfo, MRegrAccumArgs *outArgs) { float8 *stateData; uint32 len, i; uint64 statelen; /* We should be strict, but it doesn't hurt to be paranoid */ if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2)) return false; outArgs->stateAsArray = PG_GETARG_ARRAYTYPE_P(0); outArgs->newY = PG_GETARG_FLOAT8(1); outArgs->newXAsArray = PG_GETARG_ARRAYTYPE_P(2); outArgs->newX = (float8*) ARR_DATA_PTR(outArgs->newXAsArray); /* Ensure that both arrays are single dimensional float8[] arrays */ if (ARR_NULLBITMAP(outArgs->stateAsArray) || ARR_NDIM(outArgs->stateAsArray) != 1 || ARR_ELEMTYPE(outArgs->stateAsArray) != FLOAT8OID || ARR_NDIM(outArgs->newXAsArray) != 1 || ARR_ELEMTYPE(outArgs->newXAsArray) != FLOAT8OID) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); /* Only callable as a transition function */ if (!(fcinfo->context && IsA(fcinfo->context, AggState))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" not called from aggregate", format_procedure(fcinfo->flinfo->fn_oid)))); /* newXAsArray with nulls will be ignored */ if (ARR_NULLBITMAP(outArgs->newXAsArray)) return false; /* See MPP-14102. Avoid overflow while initializing len */ if (ARR_DIMS(outArgs->newXAsArray)[0] > UINT32_MAX) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("number of independent variables cannot exceed %lu", (unsigned long) UINT32_MAX))); len = ARR_DIMS(outArgs->newXAsArray)[0]; /* * See MPP-13580. At least on certain platforms and with certain versions, * LAPACK will run into an infinite loop if pinv() is called for non-finite * matrices. We extend the check also to the dependent variables. */ for (i = 0; i < len; i++) if (!isfinite(outArgs->newX[i])) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("design matrix is not finite"))); if (!isfinite(outArgs->newY)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("dependent variables are not finite"))); /* * See MPP-14102. We want to avoid (a) long int overflows and (b) making * oversized allocation requests. * We could compute the maximum number of variables so that the transition- * state length still fits into MaxAllocSize, but (assuming MaxAllocSize may * change in the future) this calculation requires taking the root out of a * 64-bit long int. Since there is no standard library function for that, and * displaying this number of merely of theoretical interest (the actual * limit is a lot lower), we simply report that the number of independent * variables is too large. * Precondition: * len < 2^32. */ statelen = STATE_LEN(len); if (!IS_FEASIBLE_STATE_LEN(statelen)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("number of independent variables is too large"))); /* * If length(outArgs->stateAsArray) == 1 then it is an unitialized state. * We extend as needed. */ if (ARR_DIMS(outArgs->stateAsArray)[0] == 1) { /* * Precondition: * IS_FEASIBLE_STATE_LEN(statelen) */ Size size = statelen * sizeof(float8) + ARR_OVERHEAD_NONULLS(1); outArgs->stateAsArray = (ArrayType *) palloc(size); SET_VARSIZE(outArgs->stateAsArray, size); outArgs->stateAsArray->ndim = 1; outArgs->stateAsArray->dataoffset = 0; outArgs->stateAsArray->elemtype = FLOAT8OID; ARR_DIMS(outArgs->stateAsArray)[0] = statelen; ARR_LBOUND(outArgs->stateAsArray)[0] = 1; stateData = (float8*) ARR_DATA_PTR(outArgs->stateAsArray); memset(stateData, 0, statelen * sizeof(float8)); stateData[0] = len; } /* * Contents of 'state' are as follows: * [0] = len(X[]) * [1] = count * [2] = sum(y) * [3] = sum(y*y) * [4:N] = sum(X'[] * y) * [N+1:M] = sum(X[] * X'[]) * N = 3 + len(X) * M = N + len(X)*len(X) */ outArgs->len = (float8*) ARR_DATA_PTR(outArgs->stateAsArray); outArgs->count = outArgs->len + 1; outArgs->sumy = outArgs->len + 2; outArgs->sumy2 = outArgs->len + 3; outArgs->Xty = outArgs->len + 4; outArgs->XtX = outArgs->len + 4 + len; /* It is an error if the number of indepent variables is not constant */ if (*outArgs->len != len) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)), errdetail("The independent-variable array is not of constant width."))); } /* Something is seriously fishy if our state has the wrong length */ if ((uint64) ARR_DIMS(outArgs->stateAsArray)[0] != statelen) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("transition function \"%s\" called with invalid parameters", format_procedure(fcinfo->flinfo->fn_oid)))); } /* Okay... All's good now do the work */ return true; }
/* * 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 alpine_miner_lr_ca_beta_accum(PG_FUNCTION_ARGS) { ArrayType *beta_arg, *columns_arg, *result; float8 *beta_data, *columns_data, *result_data; int beta_count, columns_count, result_count; bool add_intercept_arg; double weight_arg; int y_arg; int times_arg = 0; double fitness = 0.0; double gx = 0.0; double pi = 0.0; int size = 0; if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3) || PG_ARGISNULL(4) || PG_ARGISNULL(5) ||PG_ARGISNULL(6)){ 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); times_arg = PG_GETARG_INT32(6); 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)); } if (times_arg == 0) { //(weights * y + 0.5)/(weights + 1) pi = (weight_arg * y_arg + 0.5)/(weight_arg + 1); } else { pi = alpine_miner_compute_pi(beta_data, beta_count, columns_data, columns_count, add_intercept_arg); } /* compute derivative */ alpine_miner_compute_hessian(beta_count,beta_data,columns_data, result_data ,weight_arg, add_intercept_arg, pi); /* compute hessian matrix*/ //datum * compute_derivative(int columns_count,datum *columns_data, datum *result_data,bool *columns_nulls, bool*result_nulls // ,double weight_arg, int y, bool add_intercept_arg, double pi) alpine_miner_compute_xwz(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); }