00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres.h"
00011
00012 #include <float.h>
00013
00014 #include "access/gist.h"
00015 #include "access/skey.h"
00016
00017 #include "segdata.h"
00018
00019
00020
00021
00022
00023
00024 PG_MODULE_MAGIC;
00025
00026 extern int seg_yyparse();
00027 extern void seg_yyerror(const char *message);
00028 extern void seg_scanner_init(const char *str);
00029 extern void seg_scanner_finish(void);
00030
00031
00032
00033
00034
00035
00036
00037
00038 typedef struct
00039 {
00040 float center;
00041 OffsetNumber index;
00042 SEG *data;
00043 } gseg_picksplit_item;
00044
00045
00046
00047
00048 PG_FUNCTION_INFO_V1(seg_in);
00049 PG_FUNCTION_INFO_V1(seg_out);
00050 PG_FUNCTION_INFO_V1(seg_size);
00051 PG_FUNCTION_INFO_V1(seg_lower);
00052 PG_FUNCTION_INFO_V1(seg_upper);
00053 PG_FUNCTION_INFO_V1(seg_center);
00054
00055 Datum seg_in(PG_FUNCTION_ARGS);
00056 Datum seg_out(PG_FUNCTION_ARGS);
00057 Datum seg_size(PG_FUNCTION_ARGS);
00058 Datum seg_lower(PG_FUNCTION_ARGS);
00059 Datum seg_upper(PG_FUNCTION_ARGS);
00060 Datum seg_center(PG_FUNCTION_ARGS);
00061
00062
00063
00064
00065 bool gseg_consistent(GISTENTRY *entry,
00066 SEG *query,
00067 StrategyNumber strategy,
00068 Oid subtype,
00069 bool *recheck);
00070 GISTENTRY *gseg_compress(GISTENTRY *entry);
00071 GISTENTRY *gseg_decompress(GISTENTRY *entry);
00072 float *gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result);
00073 GIST_SPLITVEC *gseg_picksplit(GistEntryVector *entryvec, GIST_SPLITVEC *v);
00074 bool gseg_leaf_consistent(SEG *key, SEG *query, StrategyNumber strategy);
00075 bool gseg_internal_consistent(SEG *key, SEG *query, StrategyNumber strategy);
00076 SEG *gseg_union(GistEntryVector *entryvec, int *sizep);
00077 SEG *gseg_binary_union(SEG *r1, SEG *r2, int *sizep);
00078 bool *gseg_same(SEG *b1, SEG *b2, bool *result);
00079
00080
00081
00082
00083
00084 bool seg_same(SEG *a, SEG *b);
00085 bool seg_contains_int(SEG *a, int *b);
00086 bool seg_contains_float4(SEG *a, float4 *b);
00087 bool seg_contains_float8(SEG *a, float8 *b);
00088 bool seg_contains(SEG *a, SEG *b);
00089 bool seg_contained(SEG *a, SEG *b);
00090 bool seg_overlap(SEG *a, SEG *b);
00091 bool seg_left(SEG *a, SEG *b);
00092 bool seg_over_left(SEG *a, SEG *b);
00093 bool seg_right(SEG *a, SEG *b);
00094 bool seg_over_right(SEG *a, SEG *b);
00095 SEG *seg_union(SEG *a, SEG *b);
00096 SEG *seg_inter(SEG *a, SEG *b);
00097 void rt_seg_size(SEG *a, float *sz);
00098
00099
00100
00101
00102 int32 seg_cmp(SEG *a, SEG *b);
00103 bool seg_lt(SEG *a, SEG *b);
00104 bool seg_le(SEG *a, SEG *b);
00105 bool seg_gt(SEG *a, SEG *b);
00106 bool seg_ge(SEG *a, SEG *b);
00107 bool seg_different(SEG *a, SEG *b);
00108
00109
00110
00111
00112 static int restore(char *s, float val, int n);
00113 int significant_digits(char *s);
00114
00115
00116
00117
00118
00119
00120 Datum
00121 seg_in(PG_FUNCTION_ARGS)
00122 {
00123 char *str = PG_GETARG_CSTRING(0);
00124 SEG *result = palloc(sizeof(SEG));
00125
00126 seg_scanner_init(str);
00127
00128 if (seg_yyparse(result) != 0)
00129 seg_yyerror("bogus input");
00130
00131 seg_scanner_finish();
00132
00133 PG_RETURN_POINTER(result);
00134 }
00135
00136 Datum
00137 seg_out(PG_FUNCTION_ARGS)
00138 {
00139 SEG *seg = (SEG *) PG_GETARG_POINTER(0);
00140 char *result;
00141 char *p;
00142
00143 p = result = (char *) palloc(40);
00144
00145 if (seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~')
00146 p += sprintf(p, "%c", seg->l_ext);
00147
00148 if (seg->lower == seg->upper && seg->l_ext == seg->u_ext)
00149 {
00150
00151
00152
00153 p += restore(p, seg->lower, seg->l_sigd);
00154 }
00155 else
00156 {
00157 if (seg->l_ext != '-')
00158 {
00159
00160 p += restore(p, seg->lower, seg->l_sigd);
00161 p += sprintf(p, " ");
00162 }
00163 p += sprintf(p, "..");
00164 if (seg->u_ext != '-')
00165 {
00166
00167 p += sprintf(p, " ");
00168 if (seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~')
00169 p += sprintf(p, "%c", seg->u_ext);
00170 p += restore(p, seg->upper, seg->u_sigd);
00171 }
00172 }
00173
00174 PG_RETURN_CSTRING(result);
00175 }
00176
00177 Datum
00178 seg_center(PG_FUNCTION_ARGS)
00179 {
00180 SEG *seg = (SEG *) PG_GETARG_POINTER(0);
00181
00182 PG_RETURN_FLOAT4(((float) seg->lower + (float) seg->upper) / 2.0);
00183 }
00184
00185 Datum
00186 seg_lower(PG_FUNCTION_ARGS)
00187 {
00188 SEG *seg = (SEG *) PG_GETARG_POINTER(0);
00189
00190 PG_RETURN_FLOAT4(seg->lower);
00191 }
00192
00193 Datum
00194 seg_upper(PG_FUNCTION_ARGS)
00195 {
00196 SEG *seg = (SEG *) PG_GETARG_POINTER(0);
00197
00198 PG_RETURN_FLOAT4(seg->upper);
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 bool
00213 gseg_consistent(GISTENTRY *entry,
00214 SEG *query,
00215 StrategyNumber strategy,
00216 Oid subtype,
00217 bool *recheck)
00218 {
00219
00220 *recheck = false;
00221
00222
00223
00224
00225
00226 if (GIST_LEAF(entry))
00227 return (gseg_leaf_consistent((SEG *) DatumGetPointer(entry->key), query, strategy));
00228 else
00229 return (gseg_internal_consistent((SEG *) DatumGetPointer(entry->key), query, strategy));
00230 }
00231
00232
00233
00234
00235
00236 SEG *
00237 gseg_union(GistEntryVector *entryvec, int *sizep)
00238 {
00239 int numranges,
00240 i;
00241 SEG *out = (SEG *) NULL;
00242 SEG *tmp;
00243
00244 #ifdef GIST_DEBUG
00245 fprintf(stderr, "union\n");
00246 #endif
00247
00248 numranges = entryvec->n;
00249 tmp = (SEG *) DatumGetPointer(entryvec->vector[0].key);
00250 *sizep = sizeof(SEG);
00251
00252 for (i = 1; i < numranges; i++)
00253 {
00254 out = gseg_binary_union(tmp, (SEG *)
00255 DatumGetPointer(entryvec->vector[i].key),
00256 sizep);
00257 tmp = out;
00258 }
00259
00260 return (out);
00261 }
00262
00263
00264
00265
00266
00267 GISTENTRY *
00268 gseg_compress(GISTENTRY *entry)
00269 {
00270 return (entry);
00271 }
00272
00273 GISTENTRY *
00274 gseg_decompress(GISTENTRY *entry)
00275 {
00276 return (entry);
00277 }
00278
00279
00280
00281
00282
00283 float *
00284 gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
00285 {
00286 SEG *ud;
00287 float tmp1,
00288 tmp2;
00289
00290 ud = seg_union((SEG *) DatumGetPointer(origentry->key),
00291 (SEG *) DatumGetPointer(newentry->key));
00292 rt_seg_size(ud, &tmp1);
00293 rt_seg_size((SEG *) DatumGetPointer(origentry->key), &tmp2);
00294 *result = tmp1 - tmp2;
00295
00296 #ifdef GIST_DEBUG
00297 fprintf(stderr, "penalty\n");
00298 fprintf(stderr, "\t%g\n", *result);
00299 #endif
00300
00301 return (result);
00302 }
00303
00304
00305
00306
00307 static int
00308 gseg_picksplit_item_cmp(const void *a, const void *b)
00309 {
00310 const gseg_picksplit_item *i1 = (const gseg_picksplit_item *) a;
00311 const gseg_picksplit_item *i2 = (const gseg_picksplit_item *) b;
00312
00313 if (i1->center < i2->center)
00314 return -1;
00315 else if (i1->center == i2->center)
00316 return 0;
00317 else
00318 return 1;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328 GIST_SPLITVEC *
00329 gseg_picksplit(GistEntryVector *entryvec,
00330 GIST_SPLITVEC *v)
00331 {
00332 int i;
00333 SEG *datum_l,
00334 *datum_r,
00335 *seg;
00336 gseg_picksplit_item *sort_items;
00337 OffsetNumber *left,
00338 *right;
00339 OffsetNumber maxoff;
00340 OffsetNumber firstright;
00341
00342 #ifdef GIST_DEBUG
00343 fprintf(stderr, "picksplit\n");
00344 #endif
00345
00346
00347 maxoff = entryvec->n - 1;
00348
00349
00350
00351
00352 sort_items = (gseg_picksplit_item *)
00353 palloc(maxoff * sizeof(gseg_picksplit_item));
00354 for (i = 1; i <= maxoff; i++)
00355 {
00356 seg = (SEG *) DatumGetPointer(entryvec->vector[i].key);
00357
00358 sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f;
00359 sort_items[i - 1].index = i;
00360 sort_items[i - 1].data = seg;
00361 }
00362 qsort(sort_items, maxoff, sizeof(gseg_picksplit_item),
00363 gseg_picksplit_item_cmp);
00364
00365
00366 firstright = maxoff / 2;
00367
00368 v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
00369 v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
00370 left = v->spl_left;
00371 v->spl_nleft = 0;
00372 right = v->spl_right;
00373 v->spl_nright = 0;
00374
00375
00376
00377
00378 datum_l = (SEG *) palloc(sizeof(SEG));
00379 memcpy(datum_l, sort_items[0].data, sizeof(SEG));
00380 *left++ = sort_items[0].index;
00381 v->spl_nleft++;
00382 for (i = 1; i < firstright; i++)
00383 {
00384 datum_l = seg_union(datum_l, sort_items[i].data);
00385 *left++ = sort_items[i].index;
00386 v->spl_nleft++;
00387 }
00388
00389
00390
00391
00392 datum_r = (SEG *) palloc(sizeof(SEG));
00393 memcpy(datum_r, sort_items[firstright].data, sizeof(SEG));
00394 *right++ = sort_items[firstright].index;
00395 v->spl_nright++;
00396 for (i = firstright + 1; i < maxoff; i++)
00397 {
00398 datum_r = seg_union(datum_r, sort_items[i].data);
00399 *right++ = sort_items[i].index;
00400 v->spl_nright++;
00401 }
00402
00403 v->spl_ldatum = PointerGetDatum(datum_l);
00404 v->spl_rdatum = PointerGetDatum(datum_r);
00405
00406 return v;
00407 }
00408
00409
00410
00411
00412 bool *
00413 gseg_same(SEG *b1, SEG *b2, bool *result)
00414 {
00415 if (seg_same(b1, b2))
00416 *result = TRUE;
00417 else
00418 *result = FALSE;
00419
00420 #ifdef GIST_DEBUG
00421 fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE"));
00422 #endif
00423
00424 return (result);
00425 }
00426
00427
00428
00429
00430 bool
00431 gseg_leaf_consistent(SEG *key,
00432 SEG *query,
00433 StrategyNumber strategy)
00434 {
00435 bool retval;
00436
00437 #ifdef GIST_QUERY_DEBUG
00438 fprintf(stderr, "leaf_consistent, %d\n", strategy);
00439 #endif
00440
00441 switch (strategy)
00442 {
00443 case RTLeftStrategyNumber:
00444 retval = (bool) seg_left(key, query);
00445 break;
00446 case RTOverLeftStrategyNumber:
00447 retval = (bool) seg_over_left(key, query);
00448 break;
00449 case RTOverlapStrategyNumber:
00450 retval = (bool) seg_overlap(key, query);
00451 break;
00452 case RTOverRightStrategyNumber:
00453 retval = (bool) seg_over_right(key, query);
00454 break;
00455 case RTRightStrategyNumber:
00456 retval = (bool) seg_right(key, query);
00457 break;
00458 case RTSameStrategyNumber:
00459 retval = (bool) seg_same(key, query);
00460 break;
00461 case RTContainsStrategyNumber:
00462 case RTOldContainsStrategyNumber:
00463 retval = (bool) seg_contains(key, query);
00464 break;
00465 case RTContainedByStrategyNumber:
00466 case RTOldContainedByStrategyNumber:
00467 retval = (bool) seg_contained(key, query);
00468 break;
00469 default:
00470 retval = FALSE;
00471 }
00472 return (retval);
00473 }
00474
00475 bool
00476 gseg_internal_consistent(SEG *key,
00477 SEG *query,
00478 StrategyNumber strategy)
00479 {
00480 bool retval;
00481
00482 #ifdef GIST_QUERY_DEBUG
00483 fprintf(stderr, "internal_consistent, %d\n", strategy);
00484 #endif
00485
00486 switch (strategy)
00487 {
00488 case RTLeftStrategyNumber:
00489 retval = (bool) !seg_over_right(key, query);
00490 break;
00491 case RTOverLeftStrategyNumber:
00492 retval = (bool) !seg_right(key, query);
00493 break;
00494 case RTOverlapStrategyNumber:
00495 retval = (bool) seg_overlap(key, query);
00496 break;
00497 case RTOverRightStrategyNumber:
00498 retval = (bool) !seg_left(key, query);
00499 break;
00500 case RTRightStrategyNumber:
00501 retval = (bool) !seg_over_left(key, query);
00502 break;
00503 case RTSameStrategyNumber:
00504 case RTContainsStrategyNumber:
00505 case RTOldContainsStrategyNumber:
00506 retval = (bool) seg_contains(key, query);
00507 break;
00508 case RTContainedByStrategyNumber:
00509 case RTOldContainedByStrategyNumber:
00510 retval = (bool) seg_overlap(key, query);
00511 break;
00512 default:
00513 retval = FALSE;
00514 }
00515 return (retval);
00516 }
00517
00518 SEG *
00519 gseg_binary_union(SEG *r1, SEG *r2, int *sizep)
00520 {
00521 SEG *retval;
00522
00523 retval = seg_union(r1, r2);
00524 *sizep = sizeof(SEG);
00525
00526 return (retval);
00527 }
00528
00529
00530 bool
00531 seg_contains(SEG *a, SEG *b)
00532 {
00533 return ((a->lower <= b->lower) && (a->upper >= b->upper));
00534 }
00535
00536 bool
00537 seg_contained(SEG *a, SEG *b)
00538 {
00539 return (seg_contains(b, a));
00540 }
00541
00542
00543
00544
00545
00546 bool
00547 seg_same(SEG *a, SEG *b)
00548 {
00549 return seg_cmp(a, b) == 0;
00550 }
00551
00552
00553
00554 bool
00555 seg_overlap(SEG *a, SEG *b)
00556 {
00557 return (
00558 ((a->upper >= b->upper) && (a->lower <= b->upper))
00559 ||
00560 ((b->upper >= a->upper) && (b->lower <= a->upper))
00561 );
00562 }
00563
00564
00565
00566 bool
00567 seg_over_left(SEG *a, SEG *b)
00568 {
00569 return (a->upper <= b->upper);
00570 }
00571
00572
00573
00574 bool
00575 seg_left(SEG *a, SEG *b)
00576 {
00577 return (a->upper < b->lower);
00578 }
00579
00580
00581
00582 bool
00583 seg_right(SEG *a, SEG *b)
00584 {
00585 return (a->lower > b->upper);
00586 }
00587
00588
00589
00590 bool
00591 seg_over_right(SEG *a, SEG *b)
00592 {
00593 return (a->lower >= b->lower);
00594 }
00595
00596
00597 SEG *
00598 seg_union(SEG *a, SEG *b)
00599 {
00600 SEG *n;
00601
00602 n = (SEG *) palloc(sizeof(*n));
00603
00604
00605 if (a->upper > b->upper)
00606 {
00607 n->upper = a->upper;
00608 n->u_sigd = a->u_sigd;
00609 n->u_ext = a->u_ext;
00610 }
00611 else
00612 {
00613 n->upper = b->upper;
00614 n->u_sigd = b->u_sigd;
00615 n->u_ext = b->u_ext;
00616 }
00617
00618
00619 if (a->lower < b->lower)
00620 {
00621 n->lower = a->lower;
00622 n->l_sigd = a->l_sigd;
00623 n->l_ext = a->l_ext;
00624 }
00625 else
00626 {
00627 n->lower = b->lower;
00628 n->l_sigd = b->l_sigd;
00629 n->l_ext = b->l_ext;
00630 }
00631
00632 return (n);
00633 }
00634
00635
00636 SEG *
00637 seg_inter(SEG *a, SEG *b)
00638 {
00639 SEG *n;
00640
00641 n = (SEG *) palloc(sizeof(*n));
00642
00643
00644 if (a->upper < b->upper)
00645 {
00646 n->upper = a->upper;
00647 n->u_sigd = a->u_sigd;
00648 n->u_ext = a->u_ext;
00649 }
00650 else
00651 {
00652 n->upper = b->upper;
00653 n->u_sigd = b->u_sigd;
00654 n->u_ext = b->u_ext;
00655 }
00656
00657
00658 if (a->lower > b->lower)
00659 {
00660 n->lower = a->lower;
00661 n->l_sigd = a->l_sigd;
00662 n->l_ext = a->l_ext;
00663 }
00664 else
00665 {
00666 n->lower = b->lower;
00667 n->l_sigd = b->l_sigd;
00668 n->l_ext = b->l_ext;
00669 }
00670
00671 return (n);
00672 }
00673
00674 void
00675 rt_seg_size(SEG *a, float *size)
00676 {
00677 if (a == (SEG *) NULL || a->upper <= a->lower)
00678 *size = 0.0;
00679 else
00680 *size = (float) Abs(a->upper - a->lower);
00681
00682 return;
00683 }
00684
00685 Datum
00686 seg_size(PG_FUNCTION_ARGS)
00687 {
00688 SEG *seg = (SEG *) PG_GETARG_POINTER(0);
00689
00690 PG_RETURN_FLOAT4((float) Abs(seg->upper - seg->lower));
00691 }
00692
00693
00694
00695
00696
00697 int32
00698 seg_cmp(SEG *a, SEG *b)
00699 {
00700
00701
00702
00703 if (a->lower < b->lower)
00704 return -1;
00705 if (a->lower > b->lower)
00706 return 1;
00707
00708
00709
00710
00711
00712
00713
00714
00715 if (a->l_ext != b->l_ext)
00716 {
00717 if (a->l_ext == '-')
00718 return -1;
00719 if (b->l_ext == '-')
00720 return 1;
00721 if (a->l_ext == '<')
00722 return -1;
00723 if (b->l_ext == '<')
00724 return 1;
00725 if (a->l_ext == '>')
00726 return 1;
00727 if (b->l_ext == '>')
00728 return -1;
00729 }
00730
00731
00732
00733
00734 if (a->l_sigd < b->l_sigd)
00735 return -1;
00736 if (a->l_sigd > b->l_sigd)
00737
00738 return 1;
00739
00740
00741
00742
00743
00744 if (a->l_ext != b->l_ext)
00745 {
00746 if (a->l_ext == '~')
00747 return -1;
00748 if (b->l_ext == '~')
00749 return 1;
00750
00751 elog(ERROR, "bogus lower boundary types %d %d",
00752 (int) a->l_ext, (int) b->l_ext);
00753 }
00754
00755
00756
00757
00758
00759
00760 if (a->upper < b->upper)
00761 return -1;
00762 if (a->upper > b->upper)
00763 return 1;
00764
00765
00766
00767
00768
00769
00770
00771
00772 if (a->u_ext != b->u_ext)
00773 {
00774 if (a->u_ext == '-')
00775 return 1;
00776 if (b->u_ext == '-')
00777 return -1;
00778 if (a->u_ext == '<')
00779 return -1;
00780 if (b->u_ext == '<')
00781 return 1;
00782 if (a->u_ext == '>')
00783 return 1;
00784 if (b->u_ext == '>')
00785 return -1;
00786 }
00787
00788
00789
00790
00791
00792 if (a->u_sigd < b->u_sigd)
00793 return 1;
00794 if (a->u_sigd > b->u_sigd)
00795
00796 return -1;
00797
00798
00799
00800
00801
00802 if (a->u_ext != b->u_ext)
00803 {
00804 if (a->u_ext == '~')
00805 return 1;
00806 if (b->u_ext == '~')
00807 return -1;
00808
00809 elog(ERROR, "bogus upper boundary types %d %d",
00810 (int) a->u_ext, (int) b->u_ext);
00811 }
00812
00813 return 0;
00814 }
00815
00816 bool
00817 seg_lt(SEG *a, SEG *b)
00818 {
00819 return seg_cmp(a, b) < 0;
00820 }
00821
00822 bool
00823 seg_le(SEG *a, SEG *b)
00824 {
00825 return seg_cmp(a, b) <= 0;
00826 }
00827
00828 bool
00829 seg_gt(SEG *a, SEG *b)
00830 {
00831 return seg_cmp(a, b) > 0;
00832 }
00833
00834 bool
00835 seg_ge(SEG *a, SEG *b)
00836 {
00837 return seg_cmp(a, b) >= 0;
00838 }
00839
00840 bool
00841 seg_different(SEG *a, SEG *b)
00842 {
00843 return seg_cmp(a, b) != 0;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857 static int
00858 restore(char *result, float val, int n)
00859 {
00860 static char efmt[8] = {'%', '-', '1', '5', '.', '#', 'e', 0};
00861 char buf[25] = {
00862 '0', '0', '0', '0', '0',
00863 '0', '0', '0', '0', '0',
00864 '0', '0', '0', '0', '0',
00865 '0', '0', '0', '0', '0',
00866 '0', '0', '0', '0', '\0'
00867 };
00868 char *p;
00869 int exp;
00870 int i,
00871 dp,
00872 sign;
00873
00874
00875
00876
00877
00878 n = Min(n, FLT_DIG);
00879
00880
00881 sign = (val < 0 ? 1 : 0);
00882
00883 efmt[5] = '0' + (n - 1) % 10;
00884
00885
00886
00887 sprintf(result, efmt, val);
00888
00889
00890 for (p = result; *p != ' '; p++);
00891 *p = '\0';
00892
00893
00894 strtok(pstrdup(result), "e");
00895 exp = atoi(strtok(NULL, "e"));
00896
00897 if (exp == 0)
00898 {
00899
00900 strcpy((char *) strchr(result, 'e'), "");
00901 }
00902 else
00903 {
00904 if (Abs(exp) <= 4)
00905 {
00906
00907
00908
00909
00910 for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++)
00911 {
00912 buf[i] = *p;
00913 if (*p == '.')
00914 {
00915 dp = i--;
00916 }
00917 }
00918 if (dp == 0)
00919 dp = i--;
00920
00921
00922 if (exp > 0)
00923 {
00924 if (dp - 10 + exp >= n)
00925 {
00926
00927
00928
00929
00930
00931 exp = dp - 10 + exp - n;
00932 buf[10 + n] = '\0';
00933
00934
00935 if (n > 1)
00936 {
00937 dp = 11;
00938 for (i = 23; i > dp; i--)
00939 buf[i] = buf[i - 1];
00940 buf[dp] = '.';
00941 }
00942
00943
00944
00945
00946
00947 if (n > 1)
00948 sprintf(&buf[11 + n], "e%d", exp + n - 1);
00949 else
00950 sprintf(&buf[11], "e%d", exp + n - 1);
00951
00952 if (sign)
00953 {
00954 buf[9] = '-';
00955 strcpy(result, &buf[9]);
00956 }
00957 else
00958 strcpy(result, &buf[10]);
00959 }
00960 else
00961 {
00962 dp += exp;
00963 for (i = 23; i > dp; i--)
00964 buf[i] = buf[i - 1];
00965 buf[11 + n] = '\0';
00966 buf[dp] = '.';
00967 if (sign)
00968 {
00969 buf[9] = '-';
00970 strcpy(result, &buf[9]);
00971 }
00972 else
00973 strcpy(result, &buf[10]);
00974 }
00975 }
00976 else
00977 {
00978 dp += exp - 1;
00979 buf[10 + n] = '\0';
00980 buf[dp] = '.';
00981 if (sign)
00982 {
00983 buf[dp - 2] = '-';
00984 strcpy(result, &buf[dp - 2]);
00985 }
00986 else
00987 strcpy(result, &buf[dp - 1]);
00988 }
00989 }
00990
00991
00992
00993
00994
00995 }
00996 return (strlen(result));
00997 }
00998
00999
01000
01001
01002
01003
01004 bool
01005 seg_contains_int(SEG *a, int *b)
01006 {
01007 return ((a->lower <= *b) && (a->upper >= *b));
01008 }
01009
01010 bool
01011 seg_contains_float4(SEG *a, float4 *b)
01012 {
01013 return ((a->lower <= *b) && (a->upper >= *b));
01014 }
01015
01016 bool
01017 seg_contains_float8(SEG *a, float8 *b)
01018 {
01019 return ((a->lower <= *b) && (a->upper >= *b));
01020 }
01021
01022
01023
01024
01025 int
01026 significant_digits(char *s)
01027 {
01028 char *p = s;
01029 int n,
01030 c,
01031 zeroes;
01032
01033 zeroes = 1;
01034
01035 for (c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p));
01036
01037
01038 for (c = *p; (c == '0' || c == '.') && c != 0; c = *(++p))
01039 {
01040 if (c != '.')
01041 zeroes++;
01042 }
01043
01044
01045 for (c = *p, n = 0; c != 0; c = *(++p))
01046 {
01047 if (!((c >= '0' && c <= '9') || (c == '.')))
01048 break;
01049 if (c != '.')
01050 n++;
01051 }
01052
01053 if (!n)
01054 return (zeroes);
01055
01056 return (n);
01057 }