00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <math.h>
00018
00019 #include "access/htup_details.h"
00020 #include "catalog/pg_collation.h"
00021 #include "catalog/pg_operator.h"
00022 #include "catalog/pg_statistic.h"
00023 #include "optimizer/clauses.h"
00024 #include "utils/array.h"
00025 #include "utils/lsyscache.h"
00026 #include "utils/selfuncs.h"
00027 #include "utils/typcache.h"
00028
00029
00030
00031 #define DEFAULT_CONTAIN_SEL 0.005
00032
00033
00034 #define DEFAULT_OVERLAP_SEL 0.01
00035
00036
00037 #define DEFAULT_SEL(operator) \
00038 ((operator) == OID_ARRAY_OVERLAP_OP ? \
00039 DEFAULT_OVERLAP_SEL : DEFAULT_CONTAIN_SEL)
00040
00041 static Selectivity calc_arraycontsel(VariableStatData *vardata, Datum constval,
00042 Oid elemtype, Oid operator);
00043 static Selectivity mcelem_array_selec(ArrayType *array,
00044 TypeCacheEntry *typentry,
00045 Datum *mcelem, int nmcelem,
00046 float4 *numbers, int nnumbers,
00047 float4 *hist, int nhist,
00048 Oid operator, FmgrInfo *cmpfunc);
00049 static Selectivity mcelem_array_contain_overlap_selec(Datum *mcelem, int nmcelem,
00050 float4 *numbers, int nnumbers,
00051 Datum *array_data, int nitems,
00052 Oid operator, FmgrInfo *cmpfunc);
00053 static Selectivity mcelem_array_contained_selec(Datum *mcelem, int nmcelem,
00054 float4 *numbers, int nnumbers,
00055 Datum *array_data, int nitems,
00056 float4 *hist, int nhist,
00057 Oid operator, FmgrInfo *cmpfunc);
00058 static float *calc_hist(const float4 *hist, int nhist, int n);
00059 static float *calc_distr(const float *p, int n, int m, float rest);
00060 static int floor_log2(uint32 n);
00061 static bool find_next_mcelem(Datum *mcelem, int nmcelem, Datum value,
00062 int *index, FmgrInfo *cmpfunc);
00063 static int element_compare(const void *key1, const void *key2, void *arg);
00064 static int float_compare_desc(const void *key1, const void *key2);
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 Selectivity
00080 scalararraysel_containment(PlannerInfo *root,
00081 Node *leftop, Node *rightop,
00082 Oid elemtype, bool isEquality, bool useOr,
00083 int varRelid)
00084 {
00085 Selectivity selec;
00086 VariableStatData vardata;
00087 Datum constval;
00088 TypeCacheEntry *typentry;
00089 FmgrInfo *cmpfunc;
00090
00091
00092
00093
00094 examine_variable(root, rightop, varRelid, &vardata);
00095 if (!vardata.rel)
00096 {
00097 ReleaseVariableStats(vardata);
00098 return -1.0;
00099 }
00100
00101
00102
00103
00104 leftop = estimate_expression_value(root, leftop);
00105 if (!IsA(leftop, Const))
00106 {
00107 ReleaseVariableStats(vardata);
00108 return -1.0;
00109 }
00110 if (((Const *) leftop)->constisnull)
00111 {
00112
00113 ReleaseVariableStats(vardata);
00114 return (Selectivity) 0.0;
00115 }
00116 constval = ((Const *) leftop)->constvalue;
00117
00118
00119 typentry = lookup_type_cache(elemtype, TYPECACHE_CMP_PROC_FINFO);
00120 if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
00121 {
00122 ReleaseVariableStats(vardata);
00123 return -1.0;
00124 }
00125 cmpfunc = &typentry->cmp_proc_finfo;
00126
00127
00128
00129
00130 if (!isEquality)
00131 useOr = !useOr;
00132
00133
00134 if (HeapTupleIsValid(vardata.statsTuple))
00135 {
00136 Form_pg_statistic stats;
00137 Datum *values;
00138 int nvalues;
00139 float4 *numbers;
00140 int nnumbers;
00141 float4 *hist;
00142 int nhist;
00143
00144 stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
00145
00146
00147 if (get_attstatsslot(vardata.statsTuple,
00148 elemtype, vardata.atttypmod,
00149 STATISTIC_KIND_MCELEM, InvalidOid,
00150 NULL,
00151 &values, &nvalues,
00152 &numbers, &nnumbers))
00153 {
00154
00155 if (useOr ||
00156 !get_attstatsslot(vardata.statsTuple,
00157 elemtype, vardata.atttypmod,
00158 STATISTIC_KIND_DECHIST, InvalidOid,
00159 NULL,
00160 NULL, NULL,
00161 &hist, &nhist))
00162 {
00163 hist = NULL;
00164 nhist = 0;
00165 }
00166
00167
00168
00169
00170
00171
00172 if (useOr)
00173 selec = mcelem_array_contain_overlap_selec(values, nvalues,
00174 numbers, nnumbers,
00175 &constval, 1,
00176 OID_ARRAY_CONTAINS_OP,
00177 cmpfunc);
00178 else
00179 selec = mcelem_array_contained_selec(values, nvalues,
00180 numbers, nnumbers,
00181 &constval, 1,
00182 hist, nhist,
00183 OID_ARRAY_CONTAINED_OP,
00184 cmpfunc);
00185
00186 if (hist)
00187 free_attstatsslot(elemtype, NULL, 0, hist, nhist);
00188 free_attstatsslot(elemtype, values, nvalues, numbers, nnumbers);
00189 }
00190 else
00191 {
00192
00193 if (useOr)
00194 selec = mcelem_array_contain_overlap_selec(NULL, 0,
00195 NULL, 0,
00196 &constval, 1,
00197 OID_ARRAY_CONTAINS_OP,
00198 cmpfunc);
00199 else
00200 selec = mcelem_array_contained_selec(NULL, 0,
00201 NULL, 0,
00202 &constval, 1,
00203 NULL, 0,
00204 OID_ARRAY_CONTAINED_OP,
00205 cmpfunc);
00206 }
00207
00208
00209
00210
00211 selec *= (1.0 - stats->stanullfrac);
00212 }
00213 else
00214 {
00215
00216 if (useOr)
00217 selec = mcelem_array_contain_overlap_selec(NULL, 0,
00218 NULL, 0,
00219 &constval, 1,
00220 OID_ARRAY_CONTAINS_OP,
00221 cmpfunc);
00222 else
00223 selec = mcelem_array_contained_selec(NULL, 0,
00224 NULL, 0,
00225 &constval, 1,
00226 NULL, 0,
00227 OID_ARRAY_CONTAINED_OP,
00228 cmpfunc);
00229
00230 }
00231
00232 ReleaseVariableStats(vardata);
00233
00234
00235
00236
00237 if (!isEquality)
00238 selec = 1.0 - selec;
00239
00240 CLAMP_PROBABILITY(selec);
00241
00242 return selec;
00243 }
00244
00245
00246
00247
00248 Datum
00249 arraycontsel(PG_FUNCTION_ARGS)
00250 {
00251 PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
00252 Oid operator = PG_GETARG_OID(1);
00253 List *args = (List *) PG_GETARG_POINTER(2);
00254 int varRelid = PG_GETARG_INT32(3);
00255 VariableStatData vardata;
00256 Node *other;
00257 bool varonleft;
00258 Selectivity selec;
00259 Oid element_typeid;
00260
00261
00262
00263
00264
00265 if (!get_restriction_variable(root, args, varRelid,
00266 &vardata, &other, &varonleft))
00267 PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
00268
00269
00270
00271
00272 if (!IsA(other, Const))
00273 {
00274 ReleaseVariableStats(vardata);
00275 PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
00276 }
00277
00278
00279
00280
00281
00282 if (((Const *) other)->constisnull)
00283 {
00284 ReleaseVariableStats(vardata);
00285 PG_RETURN_FLOAT8(0.0);
00286 }
00287
00288
00289
00290
00291
00292 if (!varonleft)
00293 {
00294 if (operator == OID_ARRAY_CONTAINS_OP)
00295 operator = OID_ARRAY_CONTAINED_OP;
00296 else if (operator == OID_ARRAY_CONTAINED_OP)
00297 operator = OID_ARRAY_CONTAINS_OP;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306 element_typeid = get_base_element_type(((Const *) other)->consttype);
00307 if (element_typeid != InvalidOid &&
00308 element_typeid == get_base_element_type(vardata.vartype))
00309 {
00310 selec = calc_arraycontsel(&vardata, ((Const *) other)->constvalue,
00311 element_typeid, operator);
00312 }
00313 else
00314 {
00315 selec = DEFAULT_SEL(operator);
00316 }
00317
00318 ReleaseVariableStats(vardata);
00319
00320 CLAMP_PROBABILITY(selec);
00321
00322 PG_RETURN_FLOAT8((float8) selec);
00323 }
00324
00325
00326
00327
00328 Datum
00329 arraycontjoinsel(PG_FUNCTION_ARGS)
00330 {
00331
00332 Oid operator = PG_GETARG_OID(1);
00333
00334 PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344 static Selectivity
00345 calc_arraycontsel(VariableStatData *vardata, Datum constval,
00346 Oid elemtype, Oid operator)
00347 {
00348 Selectivity selec;
00349 TypeCacheEntry *typentry;
00350 FmgrInfo *cmpfunc;
00351 ArrayType *array;
00352
00353
00354 typentry = lookup_type_cache(elemtype, TYPECACHE_CMP_PROC_FINFO);
00355 if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
00356 return DEFAULT_SEL(operator);
00357 cmpfunc = &typentry->cmp_proc_finfo;
00358
00359
00360
00361
00362
00363 array = DatumGetArrayTypeP(constval);
00364
00365 if (HeapTupleIsValid(vardata->statsTuple))
00366 {
00367 Form_pg_statistic stats;
00368 Datum *values;
00369 int nvalues;
00370 float4 *numbers;
00371 int nnumbers;
00372 float4 *hist;
00373 int nhist;
00374
00375 stats = (Form_pg_statistic) GETSTRUCT(vardata->statsTuple);
00376
00377
00378 if (get_attstatsslot(vardata->statsTuple,
00379 elemtype, vardata->atttypmod,
00380 STATISTIC_KIND_MCELEM, InvalidOid,
00381 NULL,
00382 &values, &nvalues,
00383 &numbers, &nnumbers))
00384 {
00385
00386
00387
00388
00389 if (operator != OID_ARRAY_CONTAINED_OP ||
00390 !get_attstatsslot(vardata->statsTuple,
00391 elemtype, vardata->atttypmod,
00392 STATISTIC_KIND_DECHIST, InvalidOid,
00393 NULL,
00394 NULL, NULL,
00395 &hist, &nhist))
00396 {
00397 hist = NULL;
00398 nhist = 0;
00399 }
00400
00401
00402 selec = mcelem_array_selec(array, typentry,
00403 values, nvalues,
00404 numbers, nnumbers,
00405 hist, nhist,
00406 operator, cmpfunc);
00407
00408 if (hist)
00409 free_attstatsslot(elemtype, NULL, 0, hist, nhist);
00410 free_attstatsslot(elemtype, values, nvalues, numbers, nnumbers);
00411 }
00412 else
00413 {
00414
00415 selec = mcelem_array_selec(array, typentry,
00416 NULL, 0, NULL, 0, NULL, 0,
00417 operator, cmpfunc);
00418 }
00419
00420
00421
00422
00423 selec *= (1.0 - stats->stanullfrac);
00424 }
00425 else
00426 {
00427
00428 selec = mcelem_array_selec(array, typentry,
00429 NULL, 0, NULL, 0, NULL, 0,
00430 operator, cmpfunc);
00431
00432 }
00433
00434
00435 if (PointerGetDatum(array) != constval)
00436 pfree(array);
00437
00438 return selec;
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448 static Selectivity
00449 mcelem_array_selec(ArrayType *array, TypeCacheEntry *typentry,
00450 Datum *mcelem, int nmcelem,
00451 float4 *numbers, int nnumbers,
00452 float4 *hist, int nhist,
00453 Oid operator, FmgrInfo *cmpfunc)
00454 {
00455 Selectivity selec;
00456 int num_elems;
00457 Datum *elem_values;
00458 bool *elem_nulls;
00459 bool null_present;
00460 int nonnull_nitems;
00461 int i;
00462
00463
00464
00465
00466
00467 deconstruct_array(array,
00468 typentry->type_id,
00469 typentry->typlen,
00470 typentry->typbyval,
00471 typentry->typalign,
00472 &elem_values, &elem_nulls, &num_elems);
00473
00474
00475 nonnull_nitems = 0;
00476 null_present = false;
00477 for (i = 0; i < num_elems; i++)
00478 {
00479 if (elem_nulls[i])
00480 null_present = true;
00481 else
00482 elem_values[nonnull_nitems++] = elem_values[i];
00483 }
00484
00485
00486
00487
00488
00489 if (null_present && operator == OID_ARRAY_CONTAINS_OP)
00490 {
00491 pfree(elem_values);
00492 pfree(elem_nulls);
00493 return (Selectivity) 0.0;
00494 }
00495
00496
00497 qsort_arg(elem_values, nonnull_nitems, sizeof(Datum),
00498 element_compare, cmpfunc);
00499
00500
00501 if (operator == OID_ARRAY_CONTAINS_OP || operator == OID_ARRAY_OVERLAP_OP)
00502 selec = mcelem_array_contain_overlap_selec(mcelem, nmcelem,
00503 numbers, nnumbers,
00504 elem_values, nonnull_nitems,
00505 operator, cmpfunc);
00506 else if (operator == OID_ARRAY_CONTAINED_OP)
00507 selec = mcelem_array_contained_selec(mcelem, nmcelem,
00508 numbers, nnumbers,
00509 elem_values, nonnull_nitems,
00510 hist, nhist,
00511 operator, cmpfunc);
00512 else
00513 {
00514 elog(ERROR, "arraycontsel called for unrecognized operator %u",
00515 operator);
00516 selec = 0.0;
00517 }
00518
00519 pfree(elem_values);
00520 pfree(elem_nulls);
00521 return selec;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 static Selectivity
00542 mcelem_array_contain_overlap_selec(Datum *mcelem, int nmcelem,
00543 float4 *numbers, int nnumbers,
00544 Datum *array_data, int nitems,
00545 Oid operator, FmgrInfo *cmpfunc)
00546 {
00547 Selectivity selec,
00548 elem_selec;
00549 int mcelem_index,
00550 i;
00551 bool use_bsearch;
00552 float4 minfreq;
00553
00554
00555
00556
00557
00558
00559
00560 if (nnumbers != nmcelem + 3)
00561 {
00562 numbers = NULL;
00563 nnumbers = 0;
00564 }
00565
00566 if (numbers)
00567 {
00568
00569 minfreq = numbers[nmcelem];
00570 }
00571 else
00572 {
00573
00574 minfreq = 2 * (float4) DEFAULT_CONTAIN_SEL;
00575 }
00576
00577
00578 if (nitems * floor_log2((uint32) nmcelem) < nmcelem + nitems)
00579 use_bsearch = true;
00580 else
00581 use_bsearch = false;
00582
00583 if (operator == OID_ARRAY_CONTAINS_OP)
00584 {
00585
00586
00587
00588
00589 selec = 1.0;
00590 }
00591 else
00592 {
00593
00594
00595
00596
00597 selec = 0.0;
00598 }
00599
00600
00601 mcelem_index = 0;
00602 for (i = 0; i < nitems; i++)
00603 {
00604 bool match = false;
00605
00606
00607 if (i > 0 &&
00608 element_compare(&array_data[i - 1], &array_data[i], cmpfunc) == 0)
00609 continue;
00610
00611
00612 if (use_bsearch)
00613 {
00614 match = find_next_mcelem(mcelem, nmcelem, array_data[i],
00615 &mcelem_index, cmpfunc);
00616 }
00617 else
00618 {
00619 while (mcelem_index < nmcelem)
00620 {
00621 int cmp = element_compare(&mcelem[mcelem_index],
00622 &array_data[i],
00623 cmpfunc);
00624
00625 if (cmp < 0)
00626 mcelem_index++;
00627 else
00628 {
00629 if (cmp == 0)
00630 match = true;
00631 break;
00632 }
00633 }
00634 }
00635
00636 if (match && numbers)
00637 {
00638
00639 elem_selec = numbers[mcelem_index];
00640 mcelem_index++;
00641 }
00642 else
00643 {
00644
00645
00646
00647
00648 elem_selec = Min(DEFAULT_CONTAIN_SEL, minfreq / 2);
00649 }
00650
00651
00652
00653
00654
00655 if (operator == OID_ARRAY_CONTAINS_OP)
00656 selec *= elem_selec;
00657 else
00658 selec = selec + elem_selec - selec * elem_selec;
00659
00660
00661 CLAMP_PROBABILITY(selec);
00662 }
00663
00664 return selec;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 static Selectivity
00717 mcelem_array_contained_selec(Datum *mcelem, int nmcelem,
00718 float4 *numbers, int nnumbers,
00719 Datum *array_data, int nitems,
00720 float4 *hist, int nhist,
00721 Oid operator, FmgrInfo *cmpfunc)
00722 {
00723 int mcelem_index,
00724 i,
00725 unique_nitems = 0;
00726 float selec,
00727 minfreq,
00728 nullelem_freq;
00729 float *dist,
00730 *mcelem_dist,
00731 *hist_part;
00732 float avg_count,
00733 mult,
00734 rest;
00735 float *elem_selec;
00736
00737
00738
00739
00740
00741
00742
00743 if (numbers == NULL || nnumbers != nmcelem + 3)
00744 return DEFAULT_CONTAIN_SEL;
00745
00746
00747 if (hist == NULL || nhist < 3)
00748 return DEFAULT_CONTAIN_SEL;
00749
00750
00751
00752
00753
00754
00755 minfreq = numbers[nmcelem];
00756 nullelem_freq = numbers[nmcelem + 2];
00757 avg_count = hist[nhist - 1];
00758
00759
00760
00761
00762
00763
00764
00765 rest = avg_count;
00766
00767
00768
00769
00770
00771 mult = 1.0f;
00772
00773
00774
00775
00776
00777 elem_selec = (float *) palloc(sizeof(float) * nitems);
00778
00779
00780 mcelem_index = 0;
00781 for (i = 0; i < nitems; i++)
00782 {
00783 bool match = false;
00784
00785
00786 if (i > 0 &&
00787 element_compare(&array_data[i - 1], &array_data[i], cmpfunc) == 0)
00788 continue;
00789
00790
00791
00792
00793
00794
00795 while (mcelem_index < nmcelem)
00796 {
00797 int cmp = element_compare(&mcelem[mcelem_index],
00798 &array_data[i],
00799 cmpfunc);
00800
00801 if (cmp < 0)
00802 {
00803 mult *= (1.0f - numbers[mcelem_index]);
00804 rest -= numbers[mcelem_index];
00805 mcelem_index++;
00806 }
00807 else
00808 {
00809 if (cmp == 0)
00810 match = true;
00811 break;
00812 }
00813 }
00814
00815 if (match)
00816 {
00817
00818 elem_selec[unique_nitems] = numbers[mcelem_index];
00819
00820 rest -= numbers[mcelem_index];
00821 mcelem_index++;
00822 }
00823 else
00824 {
00825
00826
00827
00828
00829 elem_selec[unique_nitems] = Min(DEFAULT_CONTAIN_SEL,
00830 minfreq / 2);
00831 }
00832
00833 unique_nitems++;
00834 }
00835
00836
00837
00838
00839
00840 while (mcelem_index < nmcelem)
00841 {
00842 mult *= (1.0f - numbers[mcelem_index]);
00843 rest -= numbers[mcelem_index];
00844 mcelem_index++;
00845 }
00846
00847
00848
00849
00850
00851
00852
00853 mult *= exp(-rest);
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 #define EFFORT 100
00875
00876 if ((nmcelem + unique_nitems) > 0 &&
00877 unique_nitems > EFFORT * nmcelem / (nmcelem + unique_nitems))
00878 {
00879
00880
00881
00882
00883 double b = (double) nmcelem;
00884 int n;
00885
00886 n = (int) ((sqrt(b * b + 4 * EFFORT * b) - b) / 2);
00887
00888
00889 qsort(elem_selec, unique_nitems, sizeof(float),
00890 float_compare_desc);
00891 unique_nitems = n;
00892 }
00893
00894
00895
00896
00897
00898
00899 dist = calc_distr(elem_selec, unique_nitems, unique_nitems, 0.0f);
00900 mcelem_dist = calc_distr(numbers, nmcelem, unique_nitems, rest);
00901
00902
00903 hist_part = calc_hist(hist, nhist - 1, unique_nitems);
00904
00905 selec = 0.0f;
00906 for (i = 0; i <= unique_nitems; i++)
00907 {
00908
00909
00910
00911
00912
00913 if (mcelem_dist[i] > 0)
00914 selec += hist_part[i] * mult * dist[i] / mcelem_dist[i];
00915 }
00916
00917 pfree(dist);
00918 pfree(mcelem_dist);
00919 pfree(hist_part);
00920 pfree(elem_selec);
00921
00922
00923 selec *= (1.0f - nullelem_freq);
00924
00925 CLAMP_PROBABILITY(selec);
00926
00927 return selec;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 static float *
00942 calc_hist(const float4 *hist, int nhist, int n)
00943 {
00944 float *hist_part;
00945 int k,
00946 i = 0;
00947 float prev_interval = 0,
00948 next_interval;
00949 float frac;
00950
00951 hist_part = (float *) palloc((n + 1) * sizeof(float));
00952
00953
00954
00955
00956
00957
00958 frac = 1.0f / ((float) (nhist - 1));
00959
00960 for (k = 0; k <= n; k++)
00961 {
00962 int count = 0;
00963
00964
00965
00966
00967
00968
00969
00970 while (i < nhist && hist[i] <= k)
00971 {
00972 count++;
00973 i++;
00974 }
00975
00976 if (count > 0)
00977 {
00978
00979 float val;
00980
00981
00982 if (i < nhist)
00983 next_interval = hist[i] - hist[i - 1];
00984 else
00985 next_interval = 0;
00986
00987
00988
00989
00990
00991
00992 val = (float) (count - 1);
00993 if (next_interval > 0)
00994 val += 0.5f / next_interval;
00995 if (prev_interval > 0)
00996 val += 0.5f / prev_interval;
00997 hist_part[k] = frac * val;
00998
00999 prev_interval = next_interval;
01000 }
01001 else
01002 {
01003
01004 if (prev_interval > 0)
01005 hist_part[k] = frac / prev_interval;
01006 else
01007 hist_part[k] = 0.0f;
01008 }
01009 }
01010
01011 return hist_part;
01012 }
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 static float *
01031 calc_distr(const float *p, int n, int m, float rest)
01032 {
01033 float *row,
01034 *prev_row,
01035 *tmp;
01036 int i,
01037 j;
01038
01039
01040
01041
01042
01043 row = (float *) palloc((m + 1) * sizeof(float));
01044 prev_row = (float *) palloc((m + 1) * sizeof(float));
01045
01046
01047 row[0] = 1.0f;
01048 for (i = 1; i <= n; i++)
01049 {
01050 float t = p[i - 1];
01051
01052
01053 tmp = row;
01054 row = prev_row;
01055 prev_row = tmp;
01056
01057
01058 for (j = 0; j <= i && j <= m; j++)
01059 {
01060 float val = 0.0f;
01061
01062 if (j < i)
01063 val += prev_row[j] * (1.0f - t);
01064 if (j > 0)
01065 val += prev_row[j - 1] * t;
01066 row[j] = val;
01067 }
01068 }
01069
01070
01071
01072
01073
01074
01075 if (rest > DEFAULT_CONTAIN_SEL)
01076 {
01077 float t;
01078
01079
01080 tmp = row;
01081 row = prev_row;
01082 prev_row = tmp;
01083
01084 for (i = 0; i <= m; i++)
01085 row[i] = 0.0f;
01086
01087
01088 t = exp(-rest);
01089
01090
01091
01092
01093
01094 for (i = 0; i <= m; i++)
01095 {
01096 for (j = 0; j <= m - i; j++)
01097 row[j + i] += prev_row[j] * t;
01098
01099
01100 t *= rest / (float) (i + 1);
01101 }
01102 }
01103
01104 pfree(prev_row);
01105 return row;
01106 }
01107
01108
01109 static int
01110 floor_log2(uint32 n)
01111 {
01112 int logval = 0;
01113
01114 if (n == 0)
01115 return -1;
01116 if (n >= (1 << 16))
01117 {
01118 n >>= 16;
01119 logval += 16;
01120 }
01121 if (n >= (1 << 8))
01122 {
01123 n >>= 8;
01124 logval += 8;
01125 }
01126 if (n >= (1 << 4))
01127 {
01128 n >>= 4;
01129 logval += 4;
01130 }
01131 if (n >= (1 << 2))
01132 {
01133 n >>= 2;
01134 logval += 2;
01135 }
01136 if (n >= (1 << 1))
01137 {
01138 logval += 1;
01139 }
01140 return logval;
01141 }
01142
01143
01144
01145
01146
01147
01148
01149
01150 static bool
01151 find_next_mcelem(Datum *mcelem, int nmcelem, Datum value, int *index,
01152 FmgrInfo *cmpfunc)
01153 {
01154 int l = *index,
01155 r = nmcelem - 1,
01156 i,
01157 res;
01158
01159 while (l <= r)
01160 {
01161 i = (l + r) / 2;
01162 res = element_compare(&mcelem[i], &value, cmpfunc);
01163 if (res == 0)
01164 {
01165 *index = i;
01166 return true;
01167 }
01168 else if (res < 0)
01169 l = i + 1;
01170 else
01171 r = i - 1;
01172 }
01173 *index = l;
01174 return false;
01175 }
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 static int
01186 element_compare(const void *key1, const void *key2, void *arg)
01187 {
01188 Datum d1 = *((const Datum *) key1);
01189 Datum d2 = *((const Datum *) key2);
01190 FmgrInfo *cmpfunc = (FmgrInfo *) arg;
01191 Datum c;
01192
01193 c = FunctionCall2Coll(cmpfunc, DEFAULT_COLLATION_OID, d1, d2);
01194 return DatumGetInt32(c);
01195 }
01196
01197
01198
01199
01200 static int
01201 float_compare_desc(const void *key1, const void *key2)
01202 {
01203 float d1 = *((const float *) key1);
01204 float d2 = *((const float *) key2);
01205
01206 if (d1 > d2)
01207 return -1;
01208 else if (d1 < d2)
01209 return 1;
01210 else
01211 return 0;
01212 }