/* * Make array of trigrams with sorting and removing duplicate items. * * str: source string, of length slen bytes. * * Returns the sorted array of unique trigrams. */ TRGM * generate_trgm(char *str, int slen) { TRGM *trg; int len; protect_out_of_mem(slen); trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3); trg->flag = ARRKEY; len = generate_trgm_only(GETARR(trg), str, slen); SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len)); if (len == 0) return trg; /* * Make trigrams unique. */ if (len > 1) { qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm); len = unique_array(GETARR(trg), len); } SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len)); return trg; }
/* * Returns whether trg2 contains all trigrams in trg1. * This relies on the trigram arrays being sorted. */ bool trgm_contained_by(TRGM *trg1, TRGM *trg2) { trgm *ptr1, *ptr2; int len1, len2; ptr1 = GETARR(trg1); ptr2 = GETARR(trg2); len1 = ARRNELEM(trg1); len2 = ARRNELEM(trg2); while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2) { int res = CMPTRGM(ptr1, ptr2); if (res < 0) return false; else if (res > 0) ptr2++; else { ptr1++; ptr2++; } } if (ptr1 - GETARR(trg1) < len1) return false; else return true; }
Datum gin_extract_value_trgm(PG_FUNCTION_ARGS) { text *val = (text *) PG_GETARG_TEXT_P(0); int32 *nentries = (int32 *) PG_GETARG_POINTER(1); Datum *entries = NULL; TRGM *trg; int32 trglen; *nentries = 0; trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ); trglen = ARRNELEM(trg); if (trglen > 0) { trgm *ptr; int32 i; *nentries = trglen; entries = (Datum *) palloc(sizeof(Datum) * trglen); ptr = GETARR(trg); for (i = 0; i < trglen; i++) { int32 item = trgm2int(ptr); entries[i] = Int32GetDatum(item); ptr++; } } PG_RETURN_POINTER(entries); }
Datum gin_extract_trgm(PG_FUNCTION_ARGS) { text *val = (text *) PG_GETARG_TEXT_P(0); int32 *nentries = (int32 *) PG_GETARG_POINTER(1); Datum *entries = NULL; TRGM *trg; int4 trglen; *nentries = 0; trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ); trglen = ARRNELEM(trg); if (trglen > 0) { trgm *ptr; int4 i = 0, item; *nentries = (int32) trglen; entries = (Datum *) palloc(sizeof(Datum) * trglen); ptr = GETARR(trg); while (ptr - GETARR(trg) < ARRNELEM(trg)) { item = trgm2int(ptr); entries[i++] = Int32GetDatum(item); ptr++; } if (PG_NARGS() > 4) { /* * Function called from query extracting */ Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); *extra_data = (Pointer *) palloc0(sizeof(Pointer) * (*nentries)); *(int32 *) (*extra_data) = trglen; } } PG_RETURN_POINTER(entries); }
float4 cnt_sml(TRGM *trg1, TRGM *trg2) { trgm *ptr1, *ptr2; int count = 0; int len1, len2; ptr1 = GETARR(trg1); ptr2 = GETARR(trg2); len1 = ARRNELEM(trg1); len2 = ARRNELEM(trg2); /* explicit test is needed to avoid 0/0 division when both lengths are 0 */ if (len1 <= 0 || len2 <= 0) return (float4) 0.0; while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2) { int res = CMPTRGM(ptr1, ptr2); if (res < 0) ptr1++; else if (res > 0) ptr2++; else { ptr1++; ptr2++; count++; } } #ifdef DIVUNION return ((float4) count) / ((float4) (len1 + len2 - count)); #else return ((float4) count) / ((float4) ((len1 > len2) ? len1 : len2)); #endif }
float4 cnt_sml(TRGM *trg1, TRGM *trg2, bool inexact) { trgm *ptr1, *ptr2; int count = 0; int len1, len2; ptr1 = GETARR(trg1); ptr2 = GETARR(trg2); len1 = ARRNELEM(trg1); len2 = ARRNELEM(trg2); /* explicit test is needed to avoid 0/0 division when both lengths are 0 */ if (len1 <= 0 || len2 <= 0) return (float4) 0.0; while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2) { int res = CMPTRGM(ptr1, ptr2); if (res < 0) ptr1++; else if (res > 0) ptr2++; else { ptr1++; ptr2++; count++; } } /* * If inexact then len2 is equal to count, because we don't know actual * length of second string in inexact search and we can assume that count * is a lower bound of len2. */ return CALCSML(count, len1, inexact ? count : len2); }
static void makesign(BITVECP sign, GISTTYPE * a) { int4 k, len = ARRNELEM(a); int4 *ptr = GETARR(a); MemSet((void *) sign, 0, sizeof(BITVEC)); for (k = 0; k < len; k++) HASH(sign, ptr[k]); }
static void makesign(BITVECP sign, SignTSVector *a) { int32 k, len = ARRNELEM(a); int32 *ptr = GETARR(a); MemSet((void *) sign, 0, sizeof(BITVEC)); for (k = 0; k < len; k++) HASH(sign, ptr[k]); }
float4 cnt_sml(TRGM *trg1, TRGM *trg2) { trgm *ptr1, *ptr2; int count = 0; int len1, len2; ptr1 = GETARR(trg1); ptr2 = GETARR(trg2); len1 = ARRNELEM(trg1); len2 = ARRNELEM(trg2); while (ptr1 - GETARR(trg1) < len1 && ptr2 - GETARR(trg2) < len2) { int res = CMPTRGM(ptr1, ptr2); if (res < 0) ptr1++; else if (res > 0) ptr2++; else { ptr1++; ptr2++; count++; } } #ifdef DIVUNION return ((((float4) count) / ((float4) (len1 + len2 - count)))); #else return (((float) count) / ((float) ((len1 > len2) ? len1 : len2))); #endif }
/* * Return a palloc'd boolean array showing, for each trigram in "query", * whether it is present in the trigram array "key". * This relies on the "key" array being sorted, but "query" need not be. */ bool * trgm_presence_map(TRGM *query, TRGM *key) { bool *result; trgm *ptrq = GETARR(query), *ptrk = GETARR(key); int lenq = ARRNELEM(query), lenk = ARRNELEM(key), i; result = (bool *) palloc0(lenq * sizeof(bool)); /* for each query trigram, do a binary search in the key array */ for (i = 0; i < lenq; i++) { int lo = 0; int hi = lenk; while (lo < hi) { int mid = (lo + hi) / 2; int res = CMPTRGM(ptrq, ptrk + mid); if (res < 0) hi = mid; else if (res > 0) lo = mid + 1; else { result[i] = true; break; } } ptrq++; } return result; }
Datum show_trgm(PG_FUNCTION_ARGS) { text *in = PG_GETARG_TEXT_P(0); TRGM *trg; Datum *d; ArrayType *a; trgm *ptr; int i; trg = generate_trgm(VARDATA(in), VARSIZE(in) - VARHDRSZ); d = (Datum *) palloc(sizeof(Datum) * (1 + ARRNELEM(trg))); for (i = 0, ptr = GETARR(trg); i < ARRNELEM(trg); i++, ptr++) { text *item = (text *) palloc(VARHDRSZ + Max(12, pg_database_encoding_max_length() * 3)); if (pg_database_encoding_max_length() > 1 && !ISPRINTABLETRGM(ptr)) { snprintf(VARDATA(item), 12, "0x%06x", trgm2int(ptr)); SET_VARSIZE(item, VARHDRSZ + strlen(VARDATA(item))); } else { SET_VARSIZE(item, VARHDRSZ + 3); CPTRGM(VARDATA(item), ptr); } d[i] = PointerGetDatum(item); } a = construct_array( d, ARRNELEM(trg), TEXTOID, -1, false, 'i' ); for (i = 0; i < ARRNELEM(trg); i++) pfree(DatumGetPointer(d[i])); pfree(d); pfree(trg); PG_FREE_IF_COPY(in, 0); PG_RETURN_POINTER(a); }
static void makesign(BITVECP sign, TRGM *a) { int32 k, len = ARRNELEM(a); trgm *ptr = GETARR(a); int32 tmp = 0; MemSet((void *) sign, 0, sizeof(BITVEC)); SETBIT(sign, SIGLENBIT); /* set last unused bit */ for (k = 0; k < len; k++) { CPTRGM(((char *) &tmp), ptr + k); HASH(sign, tmp); } }
/* * Generates trigrams for wildcard search string. * * Returns array of trigrams that must occur in any string that matches the * wildcard string. For example, given pattern "a%bcd%" the trigrams * " a", "bcd" would be extracted. */ TRGM * generate_wildcard_trgm(const char *str, int slen) { TRGM *trg; char *buf, *buf2; trgm *tptr; int len, charlen, bytelen; const char *eword; trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3); trg->flag = ARRKEY; SET_VARSIZE(trg, TRGMHDRSIZE); if (slen + LPADDING + RPADDING < 3 || slen == 0) return trg; tptr = GETARR(trg); buf = palloc(sizeof(char) * (slen + 4)); /* * Extract trigrams from each substring extracted by get_wildcard_part. */ eword = str; while ((eword = get_wildcard_part(eword, slen - (eword - str), buf, &bytelen, &charlen)) != NULL) { #ifdef IGNORECASE buf2 = lowerstr_with_len(buf, bytelen); bytelen = strlen(buf2); #else buf2 = buf; #endif /* * count trigrams */ tptr = make_trigrams(tptr, buf2, bytelen, charlen); #ifdef IGNORECASE pfree(buf2); #endif } pfree(buf); if ((len = tptr - GETARR(trg)) == 0) return trg; /* * Make trigrams unique. */ if (len > 0) { qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm); len = unique_array(GETARR(trg), len); } SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len)); return trg; }
TRGM * generate_trgm(char *str, int slen) { TRGM *trg; char *buf; trgm *tptr; int len, charlen, bytelen; char *bword, *eword; trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3); trg->flag = ARRKEY; SET_VARSIZE(trg, TRGMHDRSIZE); if (slen + LPADDING + RPADDING < 3 || slen == 0) return trg; tptr = GETARR(trg); buf = palloc(sizeof(char) * (slen + 4)); if (LPADDING > 0) { *buf = ' '; if (LPADDING > 1) *(buf + 1) = ' '; } eword = str; while ((bword = find_word(eword, slen - (eword - str), &eword, &charlen)) != NULL) { #ifdef IGNORECASE bword = lowerstr_with_len(bword, eword - bword); bytelen = strlen(bword); #else bytelen = eword - bword; #endif memcpy(buf + LPADDING, bword, bytelen); #ifdef IGNORECASE pfree(bword); #endif buf[LPADDING + bytelen] = ' '; buf[LPADDING + bytelen + 1] = ' '; /* * count trigrams */ tptr = make_trigrams(tptr, buf, bytelen + LPADDING + RPADDING, charlen + LPADDING + RPADDING); } pfree(buf); if ((len = tptr - GETARR(trg)) == 0) return trg; if (len > 0) { qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm); len = unique_array(GETARR(trg), len); } SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len)); return trg; }
/* * Generates trigrams for wildcard search string. * * Returns array of trigrams that must occur in any string that matches the * wildcard string. For example, given pattern "a%bcd%" the trigrams * " a", "bcd" would be extracted. */ TRGM * generate_wildcard_trgm(const char *str, int slen) { TRGM *trg; char *buf, *buf2; trgm *tptr; int len, charlen, bytelen; const char *eword; /* * Guard against possible overflow in the palloc requests below. (We * don't worry about the additive constants, since palloc can detect * requests that are a little above MaxAllocSize --- we just need to * prevent integer overflow in the multiplications.) */ if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) || (Size) slen >= (MaxAllocSize / pg_database_encoding_max_length())) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("out of memory"))); trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3); trg->flag = ARRKEY; SET_VARSIZE(trg, TRGMHDRSIZE); if (slen + LPADDING + RPADDING < 3 || slen == 0) return trg; tptr = GETARR(trg); /* Allocate a buffer for blank-padded, but not yet case-folded, words */ buf = palloc(sizeof(char) * (slen + 4)); /* * Extract trigrams from each substring extracted by get_wildcard_part. */ eword = str; while ((eword = get_wildcard_part(eword, slen - (eword - str), buf, &bytelen, &charlen)) != NULL) { #ifdef IGNORECASE buf2 = lowerstr_with_len(buf, bytelen); bytelen = strlen(buf2); #else buf2 = buf; #endif /* * count trigrams */ tptr = make_trigrams(tptr, buf2, bytelen, charlen); #ifdef IGNORECASE pfree(buf2); #endif } pfree(buf); if ((len = tptr - GETARR(trg)) == 0) return trg; /* * Make trigrams unique. */ if (len > 1) { qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm); len = unique_array(GETARR(trg), len); } SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len)); return trg; }
Datum gin_extract_query_trgm(PG_FUNCTION_ARGS) { text *val = (text *) PG_GETARG_TEXT_P(0); int32 *nentries = (int32 *) PG_GETARG_POINTER(1); StrategyNumber strategy = PG_GETARG_UINT16(2); /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */ /* bool **nullFlags = (bool **) PG_GETARG_POINTER(5); */ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); Datum *entries = NULL; TRGM *trg; int32 trglen; trgm *ptr; int32 i; switch (strategy) { case SimilarityStrategyNumber: trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ); break; case ILikeStrategyNumber: #ifndef IGNORECASE elog(ERROR, "cannot handle ~~* with case-sensitive trigrams"); #endif /* FALL THRU */ case LikeStrategyNumber: /* * For wildcard search we extract all the trigrams that every * potentially-matching string must include. */ trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ); break; default: elog(ERROR, "unrecognized strategy number: %d", strategy); trg = NULL; /* keep compiler quiet */ break; } trglen = ARRNELEM(trg); *nentries = trglen; if (trglen > 0) { entries = (Datum *) palloc(sizeof(Datum) * trglen); ptr = GETARR(trg); for (i = 0; i < trglen; i++) { int32 item = trgm2int(ptr); entries[i] = Int32GetDatum(item); ptr++; } } /* * If no trigram was extracted then we have to scan all the index. */ if (trglen == 0) *searchMode = GIN_SEARCH_MODE_ALL; PG_RETURN_POINTER(entries); }
Datum gtsvector_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval = entry; if (entry->leafkey) { /* tsvector */ SignTSVector *res; TSVector val = DatumGetTSVector(entry->key); int32 len; int32 *arr; WordEntry *ptr = ARRPTR(val); char *words = STRPTR(val); len = CALCGTSIZE(ARRKEY, val->size); res = (SignTSVector *) palloc(len); SET_VARSIZE(res, len); res->flag = ARRKEY; arr = GETARR(res); len = val->size; while (len--) { pg_crc32 c; INIT_LEGACY_CRC32(c); COMP_LEGACY_CRC32(c, words + ptr->pos, ptr->len); FIN_LEGACY_CRC32(c); *arr = *(int32 *) &c; arr++; ptr++; } len = uniqueint(GETARR(res), val->size); if (len != val->size) { /* * there is a collision of hash-function; len is always less than * val->size */ len = CALCGTSIZE(ARRKEY, len); res = (SignTSVector *) repalloc((void *) res, len); SET_VARSIZE(res, len); } /* make signature, if array is too long */ if (VARSIZE(res) > TOAST_INDEX_TARGET) { SignTSVector *ressign; len = CALCGTSIZE(SIGNKEY, 0); ressign = (SignTSVector *) palloc(len); SET_VARSIZE(ressign, len); ressign->flag = SIGNKEY; makesign(GETSIGN(ressign), res); res = ressign; } retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); } else if (ISSIGNKEY(DatumGetPointer(entry->key)) && !ISALLTRUE(DatumGetPointer(entry->key))) { int32 i, len; SignTSVector *res; BITVECP sign = GETSIGN(DatumGetPointer(entry->key)); LOOPBYTE { if ((sign[i] & 0xff) != 0xff) PG_RETURN_POINTER(retval); } len = CALCGTSIZE(SIGNKEY | ALLISTRUE, 0); res = (SignTSVector *) palloc(len); SET_VARSIZE(res, len); res->flag = SIGNKEY | ALLISTRUE; retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); }
Datum gin_extract_query_trgm(PG_FUNCTION_ARGS) { text *val = (text *) PG_GETARG_TEXT_P(0); int32 *nentries = (int32 *) PG_GETARG_POINTER(1); StrategyNumber strategy = PG_GETARG_UINT16(2); /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */ Pointer **extra_data = (Pointer **) PG_GETARG_POINTER(4); /* bool **nullFlags = (bool **) PG_GETARG_POINTER(5); */ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6); Datum *entries = NULL; TRGM *trg; int32 trglen; trgm *ptr; TrgmPackedGraph *graph; int32 i; switch (strategy) { case SimilarityStrategyNumber: trg = generate_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ); break; case ILikeStrategyNumber: #ifndef IGNORECASE elog(ERROR, "cannot handle ~~* with case-sensitive trigrams"); #endif /* FALL THRU */ case LikeStrategyNumber: /* * For wildcard search we extract all the trigrams that every * potentially-matching string must include. */ trg = generate_wildcard_trgm(VARDATA(val), VARSIZE(val) - VARHDRSZ); break; case RegExpICaseStrategyNumber: #ifndef IGNORECASE elog(ERROR, "cannot handle ~* with case-sensitive trigrams"); #endif /* FALL THRU */ case RegExpStrategyNumber: trg = createTrgmNFA(val, PG_GET_COLLATION(), &graph, CurrentMemoryContext); if (trg && ARRNELEM(trg) > 0) { /* * Successful regex processing: store NFA-like graph as * extra_data. GIN API requires an array of nentries * Pointers, but we just put the same value in each element. */ trglen = ARRNELEM(trg); *extra_data = (Pointer *) palloc(sizeof(Pointer) * trglen); for (i = 0; i < trglen; i++) (*extra_data)[i] = (Pointer) graph; } else { /* No result: have to do full index scan. */ *nentries = 0; *searchMode = GIN_SEARCH_MODE_ALL; PG_RETURN_POINTER(entries); } break; default: elog(ERROR, "unrecognized strategy number: %d", strategy); trg = NULL; /* keep compiler quiet */ break; } trglen = ARRNELEM(trg); *nentries = trglen; if (trglen > 0) { entries = (Datum *) palloc(sizeof(Datum) * trglen); ptr = GETARR(trg); for (i = 0; i < trglen; i++) { int32 item = trgm2int(ptr); entries[i] = Int32GetDatum(item); ptr++; } } /* * If no trigram was extracted then we have to scan all the index. */ if (trglen == 0) *searchMode = GIN_SEARCH_MODE_ALL; PG_RETURN_POINTER(entries); }
Datum gtsvector_compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval = entry; if (entry->leafkey) { /* tsvector */ GISTTYPE *res; tsvector *val = (tsvector *) PG_DETOAST_DATUM(entry->key); int4 len; int4 *arr; WordEntry *ptr = ARRPTR(val); char *words = STRPTR(val); len = CALCGTSIZE(ARRKEY, val->size); res = (GISTTYPE *) palloc(len); SET_VARSIZE(res, len); res->flag = ARRKEY; arr = GETARR(res); len = val->size; while (len--) { *arr = crc32_sz(&words[ptr->pos], ptr->len); arr++; ptr++; } len = uniqueint(GETARR(res), val->size); if (len != val->size) { /* * there is a collision of hash-function; len is always less than * val->size */ len = CALCGTSIZE(ARRKEY, len); res = (GISTTYPE *) repalloc((void *) res, len); SET_VARSIZE(res, len); } /* make signature, if array is too long */ if (VARSIZE(res) > TOAST_INDEX_TARGET) { GISTTYPE *ressign; len = CALCGTSIZE(SIGNKEY, 0); ressign = (GISTTYPE *) palloc(len); SET_VARSIZE(ressign, len); ressign->flag = SIGNKEY; makesign(GETSIGN(ressign), res); res = ressign; } retval = (GISTENTRY *) palloc(sizeof(GISTENTRY)); gistentryinit(*retval, PointerGetDatum(res), entry->rel, entry->page, entry->offset, FALSE); } else if (ISSIGNKEY(DatumGetPointer(entry->key)) && !ISALLTRUE(DatumGetPointer(entry->key))) { int4 i, len; GISTTYPE *res; BITVECP sign = GETSIGN(DatumGetPointer(entry->key)); LOOPBYTE( if ((sign[i] & 0xff) != 0xff) PG_RETURN_POINTER(retval); );
TRGM * generate_trgm(char *str, int slen) { TRGM *trg; char *buf; trgm *tptr; int len, charlen, bytelen; char *bword, *eword; /* * Guard against possible overflow in the palloc requests below. (We * don't worry about the additive constants, since palloc can detect * requests that are a little above MaxAllocSize --- we just need to * prevent integer overflow in the multiplications.) */ if ((Size) (slen / 2) >= (MaxAllocSize / (sizeof(trgm) * 3)) || (Size) slen >= (MaxAllocSize / pg_database_encoding_max_length())) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("out of memory"))); trg = (TRGM *) palloc(TRGMHDRSIZE + sizeof(trgm) * (slen / 2 + 1) *3); trg->flag = ARRKEY; SET_VARSIZE(trg, TRGMHDRSIZE); if (slen + LPADDING + RPADDING < 3 || slen == 0) return trg; tptr = GETARR(trg); /* Allocate a buffer for case-folded, blank-padded words */ buf = (char *) palloc(slen * pg_database_encoding_max_length() + 4); if (LPADDING > 0) { *buf = ' '; if (LPADDING > 1) *(buf + 1) = ' '; } eword = str; while ((bword = find_word(eword, slen - (eword - str), &eword, &charlen)) != NULL) { #ifdef IGNORECASE bword = lowerstr_with_len(bword, eword - bword); bytelen = strlen(bword); #else bytelen = eword - bword; #endif memcpy(buf + LPADDING, bword, bytelen); #ifdef IGNORECASE pfree(bword); #endif buf[LPADDING + bytelen] = ' '; buf[LPADDING + bytelen + 1] = ' '; /* * count trigrams */ tptr = make_trigrams(tptr, buf, bytelen + LPADDING + RPADDING, charlen + LPADDING + RPADDING); } pfree(buf); if ((len = tptr - GETARR(trg)) == 0) return trg; /* * Make trigrams unique. */ if (len > 1) { qsort((void *) GETARR(trg), len, sizeof(trgm), comp_trgm); len = unique_array(GETARR(trg), len); } SET_VARSIZE(trg, CALCGTSIZE(ARRKEY, len)); return trg; }
void oclHydroGodunov(long idimStart, real_t dt, const hydroparam_t H, hydrovar_t * Hv, hydrowork_t * Hw, hydrovarwork_t * Hvw) { cl_int status; // Local variables struct timespec start, end; int i, j, idim, idimIndex; int Hmin, Hmax, Hstep, Hnxystep; int Hdimsize; int Hndim_1; int slices, iend; real_t dtdx; size_t lVarSz = H.arVarSz * H.nxystep * sizeof(real_t); long Hnxyt = H.nxyt; int clear = 0; static FILE *fic = NULL; if (fic == NULL && H.prt) { char logname[256]; sprintf(logname, "TRACE.%04d_%04d.txt", H.nproc, H.mype); fic = fopen(logname, "w"); } WHERE("hydro_godunov"); if (H.prt) fprintf(fic, "loop dt=%lg\n", dt); for (idimIndex = 0; idimIndex < 2; idimIndex++) { idim = (idimStart - 1 + idimIndex) % 2 + 1; // constant // constant dtdx = dt / H.dx; // Update boundary conditions if (H.prt) { fprintf(fic, "godunov %d\n", idim); PRINTUOLD(fic, H, Hv); } #define GETUOLD oclGetUoldFromDevice(H, Hv) start = cclock(); oclMakeBoundary(idim, H, Hv, uoldDEV); end = cclock(); functim[TIM_MAKBOU] += ccelaps(start, end); if (H.prt) {fprintf(fic, "MakeBoundary\n");} if (H.prt) {GETUOLD; PRINTUOLD(fic, H, Hv);} if (idim == 1) { Hmin = H.jmin + ExtraLayer; Hmax = H.jmax - ExtraLayer; Hdimsize = H.nxt; Hndim_1 = H.nx + 1; Hstep = H.nxystep; } else { Hmin = H.imin + ExtraLayer; Hmax = H.imax - ExtraLayer; Hdimsize = H.nyt; Hndim_1 = H.ny + 1; Hstep = H.nxystep; } Hnxystep = Hstep; for (i = Hmin; i < Hmax; i += Hstep) { long offsetIP = IHVWS(0, 0, IP); long offsetID = IHVWS(0, 0, ID); int Hnxyt = H.nxyt; iend = i + Hstep; if (iend >= Hmax) iend = Hmax; slices = iend - i; if (clear) oclMemset(uDEV, 0, lVarSz); start = cclock(); oclGatherConservativeVars(idim, i, H.imin, H.imax, H.jmin, H.jmax, H.nvar, H.nxt, H.nyt, H.nxyt, slices, Hnxystep, uoldDEV, uDEV); end = cclock(); functim[TIM_GATCON] += ccelaps(start, end); if (H.prt) {fprintf(fic, "ConservativeVars %ld %ld %ld %ld %d %d\n", H.nvar, H.nxt, H.nyt, H.nxyt, slices, Hstep);} if (H.prt) { GETARRV(uDEV, Hvw->u); } PRINTARRAYV2(fic, Hvw->u, Hdimsize, "u", H); // Convert to primitive variables start = cclock(); oclConstoprim(Hdimsize, H.nxyt, H.nvar, H.smallr, slices, Hnxystep, uDEV, qDEV, eDEV); end = cclock(); functim[TIM_CONPRI] += ccelaps(start, end); if (H.prt) { GETARR (eDEV, Hw->e); } if (H.prt) { GETARRV(qDEV, Hvw->q); } PRINTARRAY(fic, Hw->e, Hdimsize, "e", H); PRINTARRAYV2(fic, Hvw->q, Hdimsize, "q", H); start = cclock(); oclEquationOfState(offsetIP, offsetID, 0, Hdimsize, H.smallc, H.gamma, slices, H.nxyt, qDEV, eDEV, cDEV); end = cclock(); functim[TIM_EOS] += ccelaps(start, end); if (H.prt) { GETARR (cDEV, Hw->c); } PRINTARRAY(fic, Hw->c, Hdimsize, "c", H); if (H.prt) { GETARRV (qDEV, Hvw->q); } PRINTARRAYV2(fic, Hvw->q, Hdimsize, "q", H); if (clear) oclMemset(dqDEV, 0, H.arVarSz * H.nxystep); // Characteristic tracing if (H.iorder != 1) { if (clear) oclMemset(dqDEV, 0, H.arVarSz); start = cclock(); oclSlope(Hdimsize, H.nvar, H.nxyt, H.slope_type, slices, Hstep, qDEV, dqDEV); end = cclock(); functim[TIM_SLOPE] += ccelaps(start, end); if (H.prt) { GETARRV(dqDEV, Hvw->dq); } PRINTARRAYV2(fic, Hvw->dq, Hdimsize, "dq", H); } start = cclock(); oclTrace(dtdx, Hdimsize, H.scheme, H.nvar, H.nxyt, slices, Hstep, qDEV, dqDEV, cDEV, qxmDEV, qxpDEV); end = cclock(); functim[TIM_TRACE] += ccelaps(start, end); if (H.prt) { GETARRV(qxmDEV, Hvw->qxm); } if (H.prt) { GETARRV(qxpDEV, Hvw->qxp); } PRINTARRAYV2(fic, Hvw->qxm, Hdimsize, "qxm", H); PRINTARRAYV2(fic, Hvw->qxp, Hdimsize, "qxp", H); start = cclock(); oclQleftright(idim, H.nx, H.ny, H.nxyt, H.nvar, slices, Hstep, qxmDEV, qxpDEV, qleftDEV, qrightDEV); end = cclock(); functim[TIM_QLEFTR] += ccelaps(start, end); if (H.prt) { GETARRV(qleftDEV, Hvw->qleft); } if (H.prt) { GETARRV(qrightDEV, Hvw->qright); } PRINTARRAYV2(fic, Hvw->qleft, Hdimsize, "qleft", H); PRINTARRAYV2(fic, Hvw->qright, Hdimsize, "qright", H); // Solve Riemann problem at interfaces start = cclock(); oclRiemann(Hndim_1, H.smallr, H.smallc, H.gamma, H.niter_riemann, H.nvar, H.nxyt, slices, Hstep, qleftDEV, qrightDEV, qgdnvDEV,sgnmDEV); end = cclock(); functim[TIM_RIEMAN] += ccelaps(start, end); if (H.prt) { GETARRV(qgdnvDEV, Hvw->qgdnv); } PRINTARRAYV2(fic, Hvw->qgdnv, Hdimsize, "qgdnv", H); // Compute fluxes if (clear) oclMemset(fluxDEV, 0, H.arVarSz); start = cclock(); oclCmpflx(Hdimsize, H.nxyt, H.nvar, H.gamma, slices, Hnxystep, qgdnvDEV, fluxDEV); end = cclock(); functim[TIM_CMPFLX] += ccelaps(start, end); if (H.prt) { GETARRV(fluxDEV, Hvw->flux); } PRINTARRAYV2(fic, Hvw->flux, Hdimsize, "flux", H); if (H.prt) { GETARRV(uDEV, Hvw->u); } PRINTARRAYV2(fic, Hvw->u, Hdimsize, "u", H); // if (H.prt) { // GETUOLD; PRINTUOLD(fic, H, Hv); // } if (H.prt) fprintf(fic, "dxdt=%lg\n", dtdx); start = cclock(); oclUpdateConservativeVars(idim, i, dtdx, H.imin, H.imax, H.jmin, H.jmax, H.nvar, H.nxt, H.nyt, H.nxyt, slices, Hnxystep, uoldDEV, uDEV, fluxDEV); end = cclock(); functim[TIM_UPDCON] += ccelaps(start, end); if (H.prt) { GETUOLD; PRINTUOLD(fic, H, Hv); } } // for j if (H.prt) { // printf("After pass %d\n", idim); PRINTUOLD(fic, H, Hv); } } } // hydro_godunov