rt_mbr.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:21k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & Ramil Kalimullin & MySQL Finland AB 
  2.    & TCX DataKonsult AB
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  17. #include "myisamdef.h"
  18. #ifdef HAVE_RTREE_KEYS
  19. #include "rt_index.h"
  20. #include "rt_mbr.h"
  21. #define INTERSECT_CMP(amin, amax, bmin, bmax) ((amin >  bmax) || (bmin >  amax))
  22. #define CONTAIN_CMP(amin, amax, bmin, bmax) ((bmin > amin)  || (bmax <  amax))
  23. #define WITHIN_CMP(amin, amax, bmin, bmax) ((amin > bmin)  || (amax <  bmax))
  24. #define DISJOINT_CMP(amin, amax, bmin, bmax) ((amin <= bmax) && (bmin <= amax))
  25. #define EQUAL_CMP(amin, amax, bmin, bmax) ((amin != bmin) || (amax != bmax))
  26. #define FCMP(A, B) ((int)(A) - (int)(B))
  27. #define p_inc(A, B, X)  {A += X; B += X;}
  28. #define RT_CMP(nextflag) 
  29.   if (nextflag & MBR_INTERSECT) 
  30.   { 
  31.     if (INTERSECT_CMP(amin, amax, bmin, bmax)) 
  32.       return 1; 
  33.   } 
  34.   else if (nextflag & MBR_CONTAIN) 
  35.   { 
  36.     if (CONTAIN_CMP(amin, amax, bmin, bmax)) 
  37.       return 1; 
  38.   } 
  39.   else if (nextflag & MBR_WITHIN) 
  40.   { 
  41.     if (WITHIN_CMP(amin, amax, bmin, bmax)) 
  42.       return 1; 
  43.   } 
  44.   else if (nextflag & MBR_EQUAL)  
  45.   { 
  46.     if (EQUAL_CMP(amin, amax, bmin, bmax)) 
  47.       return 1; 
  48.   } 
  49.   else /* if (nextflag & MBR_DISJOINT) */ 
  50.   { 
  51.     if (DISJOINT_CMP(amin, amax, bmin, bmax)) 
  52.       return 1; 
  53.   }
  54. #define RT_CMP_KORR(type, korr_func, len, nextflag) 
  55.   type amin, amax, bmin, bmax; 
  56.   amin = korr_func(a); 
  57.   bmin = korr_func(b); 
  58.   amax = korr_func(a+len); 
  59.   bmax = korr_func(b+len); 
  60.   RT_CMP(nextflag); 
  61. }
  62. #define RT_CMP_GET(type, get_func, len, nextflag) 
  63.   type amin, amax, bmin, bmax; 
  64.   get_func(amin, a); 
  65.   get_func(bmin, b); 
  66.   get_func(amax, a+len); 
  67.   get_func(bmax, b+len); 
  68.   RT_CMP(nextflag); 
  69. }
  70. /*
  71.  Compares two keys a and b depending on nextflag
  72.  nextflag can contain these flags:
  73.    MBR_INTERSECT(a,b)  a overlaps b
  74.    MBR_CONTAIN(a,b)    a contains b
  75.    MBR_DISJOINT(a,b)   a disjoint b
  76.    MBR_WITHIN(a,b)     a within   b
  77.    MBR_EQUAL(a,b)      All coordinates of MBRs are equal
  78.    MBR_DATA(a,b)       Data reference is the same
  79.  Returns 0 on success.
  80. */
  81. int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length, 
  82.                   uint nextflag)
  83. {
  84.   for (; (int) key_length > 0; keyseg += 2 )
  85.   {
  86.     uint32 keyseg_length;
  87.     switch ((enum ha_base_keytype) keyseg->type) {
  88.     case HA_KEYTYPE_INT8:
  89.       RT_CMP_KORR(int8, mi_sint1korr, 1, nextflag);
  90.       break;
  91.     case HA_KEYTYPE_BINARY:
  92.       RT_CMP_KORR(uint8, mi_uint1korr, 1, nextflag);
  93.       break;
  94.     case HA_KEYTYPE_SHORT_INT:
  95.       RT_CMP_KORR(int16, mi_sint2korr, 2, nextflag);
  96.       break;
  97.     case HA_KEYTYPE_USHORT_INT:
  98.       RT_CMP_KORR(uint16, mi_uint2korr, 2, nextflag);
  99.       break;
  100.     case HA_KEYTYPE_INT24:
  101.       RT_CMP_KORR(int32, mi_sint3korr, 3, nextflag);
  102.       break;
  103.     case HA_KEYTYPE_UINT24:
  104.       RT_CMP_KORR(uint32, mi_uint3korr, 3, nextflag);
  105.       break;
  106.     case HA_KEYTYPE_LONG_INT:
  107.       RT_CMP_KORR(int32, mi_sint4korr, 4, nextflag);
  108.       break;
  109.     case HA_KEYTYPE_ULONG_INT:
  110.       RT_CMP_KORR(uint32, mi_uint4korr, 4, nextflag);
  111.       break;
  112. #ifdef HAVE_LONG_LONG
  113.     case HA_KEYTYPE_LONGLONG:
  114.       RT_CMP_KORR(longlong, mi_sint8korr, 8, nextflag)
  115.       break;
  116.     case HA_KEYTYPE_ULONGLONG:
  117.       RT_CMP_KORR(ulonglong, mi_uint8korr, 8, nextflag)
  118.       break;
  119. #endif
  120.     case HA_KEYTYPE_FLOAT:
  121.       /* The following should be safe, even if we compare doubles */
  122.       RT_CMP_GET(float, mi_float4get, 4, nextflag);
  123.       break;
  124.     case HA_KEYTYPE_DOUBLE:
  125.       RT_CMP_GET(double, mi_float8get, 8, nextflag);
  126.       break;
  127.     case HA_KEYTYPE_END:
  128.       goto end;
  129.     default:
  130.       return 1;
  131.     }
  132.     keyseg_length= keyseg->length * 2;
  133.     key_length-= keyseg_length;
  134.     a+= keyseg_length;
  135.     b+= keyseg_length;
  136.   }
  137. end:
  138.   if (nextflag & MBR_DATA)
  139.   {
  140.     uchar *end = a + keyseg->length;
  141.     do
  142.     {
  143.       if (*a++ != *b++)
  144.         return FCMP(a[-1], b[-1]);
  145.     } while (a != end);
  146.   }
  147.   return 0;
  148. }
  149. #define RT_VOL_KORR(type, korr_func, len, cast) 
  150.   type amin, amax; 
  151.   amin = korr_func(a); 
  152.   amax = korr_func(a+len); 
  153.   res *= (cast(amax) - cast(amin)); 
  154. }
  155. #define RT_VOL_GET(type, get_func, len, cast) 
  156.   type amin, amax; 
  157.   get_func(amin, a); 
  158.   get_func(amax, a+len); 
  159.   res *= (cast(amax) - cast(amin)); 
  160. }
  161. /*
  162.  Calculates rectangle volume
  163. */
  164. double rtree_rect_volume(HA_KEYSEG *keyseg, uchar *a, uint key_length)
  165. {
  166.   double res = 1;
  167.   for (; (int)key_length > 0; keyseg += 2)
  168.   {
  169.     uint32 keyseg_length;
  170.     switch ((enum ha_base_keytype) keyseg->type) {
  171.     case HA_KEYTYPE_INT8:
  172.       RT_VOL_KORR(int8, mi_sint1korr, 1, (double));
  173.       break;
  174.     case HA_KEYTYPE_BINARY:
  175.       RT_VOL_KORR(uint8, mi_uint1korr, 1, (double));
  176.       break;
  177.     case HA_KEYTYPE_SHORT_INT:
  178.       RT_VOL_KORR(int16, mi_sint2korr, 2, (double));
  179.       break;
  180.     case HA_KEYTYPE_USHORT_INT:
  181.       RT_VOL_KORR(uint16, mi_uint2korr, 2, (double));
  182.       break;
  183.     case HA_KEYTYPE_INT24:
  184.       RT_VOL_KORR(int32, mi_sint3korr, 3, (double));
  185.       break;
  186.     case HA_KEYTYPE_UINT24:
  187.       RT_VOL_KORR(uint32, mi_uint3korr, 3, (double));
  188.       break;
  189.     case HA_KEYTYPE_LONG_INT:
  190.       RT_VOL_KORR(int32, mi_sint4korr, 4, (double));
  191.       break;
  192.     case HA_KEYTYPE_ULONG_INT:
  193.       RT_VOL_KORR(uint32, mi_uint4korr, 4, (double));
  194.       break;
  195. #ifdef HAVE_LONG_LONG
  196.     case HA_KEYTYPE_LONGLONG:
  197.       RT_VOL_KORR(longlong, mi_sint8korr, 8, (double));
  198.       break;
  199.     case HA_KEYTYPE_ULONGLONG:
  200.       RT_VOL_KORR(longlong, mi_sint8korr, 8, ulonglong2double);
  201.       break;
  202. #endif
  203.     case HA_KEYTYPE_FLOAT:
  204.       RT_VOL_GET(float, mi_float4get, 4, (double));
  205.       break;
  206.     case HA_KEYTYPE_DOUBLE:
  207.       RT_VOL_GET(double, mi_float8get, 8, (double));
  208.       break;
  209.     case HA_KEYTYPE_END:
  210.       key_length = 0;
  211.       break;
  212.     default:
  213.       return -1;
  214.     }
  215.     keyseg_length= keyseg->length * 2;
  216.     key_length-= keyseg_length;
  217.     a+= keyseg_length;
  218.   }
  219.   return res;
  220. }
  221. #define RT_D_MBR_KORR(type, korr_func, len, cast) 
  222.   type amin, amax; 
  223.   amin = korr_func(a); 
  224.   amax = korr_func(a+len); 
  225.   *res++ = cast(amin); 
  226.   *res++ = cast(amax); 
  227. }
  228. #define RT_D_MBR_GET(type, get_func, len, cast) 
  229.   type amin, amax; 
  230.   get_func(amin, a); 
  231.   get_func(amax, a+len); 
  232.   *res++ = cast(amin); 
  233.   *res++ = cast(amax); 
  234. }
  235. /*
  236.   Creates an MBR as an array of doubles.
  237. */
  238. int rtree_d_mbr(HA_KEYSEG *keyseg, uchar *a, uint key_length, double *res)
  239. {
  240.   for (; (int)key_length > 0; keyseg += 2)
  241.   {
  242.     uint32 keyseg_length;
  243.     switch ((enum ha_base_keytype) keyseg->type) {
  244.     case HA_KEYTYPE_INT8:
  245.       RT_D_MBR_KORR(int8, mi_sint1korr, 1, (double));
  246.       break;
  247.     case HA_KEYTYPE_BINARY:
  248.       RT_D_MBR_KORR(uint8, mi_uint1korr, 1, (double));
  249.       break;
  250.     case HA_KEYTYPE_SHORT_INT:
  251.       RT_D_MBR_KORR(int16, mi_sint2korr, 2, (double));
  252.       break;
  253.     case HA_KEYTYPE_USHORT_INT:
  254.       RT_D_MBR_KORR(uint16, mi_uint2korr, 2, (double));
  255.       break;
  256.     case HA_KEYTYPE_INT24:
  257.       RT_D_MBR_KORR(int32, mi_sint3korr, 3, (double));
  258.       break;
  259.     case HA_KEYTYPE_UINT24:
  260.       RT_D_MBR_KORR(uint32, mi_uint3korr, 3, (double));
  261.       break;
  262.     case HA_KEYTYPE_LONG_INT:
  263.       RT_D_MBR_KORR(int32, mi_sint4korr, 4, (double));
  264.       break;
  265.     case HA_KEYTYPE_ULONG_INT:
  266.       RT_D_MBR_KORR(uint32, mi_uint4korr, 4, (double));
  267.       break;
  268. #ifdef HAVE_LONG_LONG
  269.     case HA_KEYTYPE_LONGLONG:
  270.       RT_D_MBR_KORR(longlong, mi_sint8korr, 8, (double));
  271.       break;
  272.     case HA_KEYTYPE_ULONGLONG:
  273.       RT_D_MBR_KORR(longlong, mi_sint8korr, 8, ulonglong2double);
  274.       break;
  275. #endif
  276.     case HA_KEYTYPE_FLOAT:
  277.       RT_D_MBR_GET(float, mi_float4get, 4, (double));
  278.       break;
  279.     case HA_KEYTYPE_DOUBLE:
  280.       RT_D_MBR_GET(double, mi_float8get, 8, (double));
  281.       break;
  282.     case HA_KEYTYPE_END:
  283.       key_length = 0;
  284.       break;
  285.     default:
  286.       return 1;
  287.     }
  288.     keyseg_length= keyseg->length * 2;
  289.     key_length-= keyseg_length;
  290.     a+= keyseg_length;
  291.   }
  292.   return 0;
  293. }
  294. #define RT_COMB_KORR(type, korr_func, store_func, len) 
  295.   type amin, amax, bmin, bmax; 
  296.   amin = korr_func(a); 
  297.   bmin = korr_func(b); 
  298.   amax = korr_func(a+len); 
  299.   bmax = korr_func(b+len); 
  300.   amin = min(amin, bmin); 
  301.   amax = max(amax, bmax); 
  302.   store_func(c, amin); 
  303.   store_func(c+len, amax); 
  304. }
  305. #define RT_COMB_GET(type, get_func, store_func, len) 
  306.   type amin, amax, bmin, bmax; 
  307.   get_func(amin, a); 
  308.   get_func(bmin, b); 
  309.   get_func(amax, a+len); 
  310.   get_func(bmax, b+len); 
  311.   amin = min(amin, bmin); 
  312.   amax = max(amax, bmax); 
  313.   store_func(c, amin); 
  314.   store_func(c+len, amax); 
  315. }
  316. /*
  317.   Creates common minimal bounding rectungle
  318.   for two input rectagnles a and b
  319.   Result is written to c
  320. */
  321. int rtree_combine_rect(HA_KEYSEG *keyseg, uchar* a, uchar* b, uchar* c, 
  322.        uint key_length)
  323. {
  324.   for ( ; (int) key_length > 0 ; keyseg += 2)
  325.   {
  326.     uint32 keyseg_length;
  327.     switch ((enum ha_base_keytype) keyseg->type) {
  328.     case HA_KEYTYPE_INT8:
  329.       RT_COMB_KORR(int8, mi_sint1korr, mi_int1store, 1);
  330.       break;
  331.     case HA_KEYTYPE_BINARY:
  332.       RT_COMB_KORR(uint8, mi_uint1korr, mi_int1store, 1);
  333.       break;
  334.     case HA_KEYTYPE_SHORT_INT:
  335.       RT_COMB_KORR(int16, mi_sint2korr, mi_int2store, 2);
  336.       break;
  337.     case HA_KEYTYPE_USHORT_INT:
  338.       RT_COMB_KORR(uint16, mi_uint2korr, mi_int2store, 2);
  339.       break;
  340.     case HA_KEYTYPE_INT24:
  341.       RT_COMB_KORR(int32, mi_sint3korr, mi_int3store, 3);
  342.       break;
  343.     case HA_KEYTYPE_UINT24:
  344.       RT_COMB_KORR(uint32, mi_uint3korr, mi_int3store, 3);
  345.       break;
  346.     case HA_KEYTYPE_LONG_INT:
  347.       RT_COMB_KORR(int32, mi_sint4korr, mi_int4store, 4);
  348.       break;
  349.     case HA_KEYTYPE_ULONG_INT:
  350.       RT_COMB_KORR(uint32, mi_uint4korr, mi_int4store, 4);
  351.       break;
  352. #ifdef HAVE_LONG_LONG
  353.     case HA_KEYTYPE_LONGLONG:
  354.       RT_COMB_KORR(longlong, mi_sint8korr, mi_int8store, 8);
  355.       break;
  356.     case HA_KEYTYPE_ULONGLONG:
  357.       RT_COMB_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
  358.       break;
  359. #endif
  360.     case HA_KEYTYPE_FLOAT:
  361.       RT_COMB_GET(float, mi_float4get, mi_float4store, 4);
  362.       break;
  363.     case HA_KEYTYPE_DOUBLE:
  364.       RT_COMB_GET(double, mi_float8get, mi_float8store, 8);
  365.       break;
  366.     case HA_KEYTYPE_END:
  367.       return 0;
  368.     default:
  369.       return 1;
  370.     }
  371.     keyseg_length= keyseg->length * 2;
  372.     key_length-= keyseg_length;
  373.     a+= keyseg_length;
  374.     b+= keyseg_length;
  375.     c+= keyseg_length;
  376.   }
  377.   return 0;
  378. }
  379. #define RT_OVL_AREA_KORR(type, korr_func, len) 
  380.   type amin, amax, bmin, bmax; 
  381.   amin = korr_func(a); 
  382.   bmin = korr_func(b); 
  383.   amax = korr_func(a+len); 
  384.   bmax = korr_func(b+len); 
  385.   amin = max(amin, bmin); 
  386.   amax = min(amax, bmax); 
  387.   if (amin >= amax) 
  388.     return 0; 
  389.   res *= amax - amin; 
  390. }
  391. #define RT_OVL_AREA_GET(type, get_func, len) 
  392.   type amin, amax, bmin, bmax; 
  393.   get_func(amin, a); 
  394.   get_func(bmin, b); 
  395.   get_func(amax, a+len); 
  396.   get_func(bmax, b+len); 
  397.   amin = max(amin, bmin); 
  398.   amax = min(amax, bmax); 
  399.   if (amin >= amax)  
  400.     return 0; 
  401.   res *= amax - amin; 
  402. }
  403. /*
  404. Calculates overlapping area of two MBRs a & b
  405. */
  406. double rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b, 
  407.                              uint key_length)
  408. {
  409.   double res = 1;
  410.   for (; (int) key_length > 0 ; keyseg += 2)
  411.   {
  412.     uint32 keyseg_length;
  413.     switch ((enum ha_base_keytype) keyseg->type) {
  414.     case HA_KEYTYPE_INT8:
  415.       RT_OVL_AREA_KORR(int8, mi_sint1korr, 1);
  416.       break;
  417.     case HA_KEYTYPE_BINARY:
  418.       RT_OVL_AREA_KORR(uint8, mi_uint1korr, 1);
  419.       break;
  420.     case HA_KEYTYPE_SHORT_INT:
  421.       RT_OVL_AREA_KORR(int16, mi_sint2korr, 2);
  422.       break;
  423.     case HA_KEYTYPE_USHORT_INT:
  424.       RT_OVL_AREA_KORR(uint16, mi_uint2korr, 2);
  425.       break;
  426.     case HA_KEYTYPE_INT24:
  427.       RT_OVL_AREA_KORR(int32, mi_sint3korr, 3);
  428.       break;
  429.     case HA_KEYTYPE_UINT24:
  430.       RT_OVL_AREA_KORR(uint32, mi_uint3korr, 3);
  431.       break;
  432.     case HA_KEYTYPE_LONG_INT:
  433.       RT_OVL_AREA_KORR(int32, mi_sint4korr, 4);
  434.       break;
  435.     case HA_KEYTYPE_ULONG_INT:
  436.       RT_OVL_AREA_KORR(uint32, mi_uint4korr, 4);
  437.       break;
  438. #ifdef HAVE_LONG_LONG
  439.     case HA_KEYTYPE_LONGLONG:
  440.       RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
  441.       break;
  442.     case HA_KEYTYPE_ULONGLONG:
  443.       RT_OVL_AREA_KORR(longlong, mi_sint8korr, 8);
  444.       break;
  445. #endif
  446.     case HA_KEYTYPE_FLOAT:
  447.       RT_OVL_AREA_GET(float, mi_float4get, 4);
  448.       break;
  449.     case HA_KEYTYPE_DOUBLE:
  450.       RT_OVL_AREA_GET(double, mi_float8get, 8);
  451.       break;
  452.     case HA_KEYTYPE_END:
  453.       return res;
  454.     default:
  455.       return -1;
  456.     }
  457.     keyseg_length= keyseg->length * 2;
  458.     key_length-= keyseg_length;
  459.     a+= keyseg_length;
  460.     b+= keyseg_length;
  461.   }
  462.   return res;
  463. }
  464. #define RT_AREA_INC_KORR(type, korr_func, len) 
  465.    type amin, amax, bmin, bmax; 
  466.    amin = korr_func(a); 
  467.    bmin = korr_func(b); 
  468.    amax = korr_func(a+len); 
  469.    bmax = korr_func(b+len); 
  470.    a_area *= (((double)amax) - ((double)amin)); 
  471.    loc_ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); 
  472. }
  473. #define RT_AREA_INC_GET(type, get_func, len)
  474. {
  475.    type amin, amax, bmin, bmax; 
  476.    get_func(amin, a); 
  477.    get_func(bmin, b); 
  478.    get_func(amax, a+len); 
  479.    get_func(bmax, b+len); 
  480.    a_area *= (((double)amax) - ((double)amin)); 
  481.    loc_ab_area *= ((double)max(amax, bmax) - (double)min(amin, bmin)); 
  482. }
  483. /*
  484. Calculates MBR_AREA(a+b) - MBR_AREA(a)
  485. */
  486. double rtree_area_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, 
  487.                           uint key_length, double *ab_area)
  488. {
  489.   double a_area= 1.0;
  490.   double loc_ab_area= 1.0;
  491.   
  492.   *ab_area= 1.0;
  493.   for (; (int)key_length > 0; keyseg += 2)
  494.   {
  495.     uint32 keyseg_length;
  496.     if (keyseg->null_bit)                       /* Handle NULL part */
  497.       return -1;
  498.     switch ((enum ha_base_keytype) keyseg->type) {
  499.     case HA_KEYTYPE_INT8:
  500.       RT_AREA_INC_KORR(int8, mi_sint1korr, 1);
  501.       break;
  502.     case HA_KEYTYPE_BINARY:
  503.       RT_AREA_INC_KORR(uint8, mi_uint1korr, 1);
  504.       break;
  505.     case HA_KEYTYPE_SHORT_INT:
  506.       RT_AREA_INC_KORR(int16, mi_sint2korr, 2);
  507.       break;
  508.     case HA_KEYTYPE_USHORT_INT:
  509.       RT_AREA_INC_KORR(uint16, mi_uint2korr, 2);
  510.       break;
  511.     case HA_KEYTYPE_INT24:
  512.       RT_AREA_INC_KORR(int32, mi_sint3korr, 3);
  513.       break;
  514.     case HA_KEYTYPE_UINT24:
  515.       RT_AREA_INC_KORR(int32, mi_uint3korr, 3);
  516.       break;
  517.     case HA_KEYTYPE_LONG_INT:
  518.       RT_AREA_INC_KORR(int32, mi_sint4korr, 4);
  519.       break;
  520.     case HA_KEYTYPE_ULONG_INT:
  521.       RT_AREA_INC_KORR(uint32, mi_uint4korr, 4);
  522.       break;
  523. #ifdef HAVE_LONG_LONG
  524.     case HA_KEYTYPE_LONGLONG:
  525.       RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
  526.       break;
  527.     case HA_KEYTYPE_ULONGLONG:
  528.       RT_AREA_INC_KORR(longlong, mi_sint8korr, 8);
  529.       break;
  530. #endif
  531.     case HA_KEYTYPE_FLOAT:
  532.       RT_AREA_INC_GET(float, mi_float4get, 4);
  533.       break;
  534.     case HA_KEYTYPE_DOUBLE:
  535.       RT_AREA_INC_GET(double, mi_float8get, 8);
  536.       break;
  537.     case HA_KEYTYPE_END:
  538.       goto safe_end;
  539.     default:
  540.       return -1;
  541.     }
  542.     keyseg_length= keyseg->length * 2;
  543.     key_length-= keyseg_length;
  544.     a+= keyseg_length;
  545.     b+= keyseg_length;
  546.   }
  547. safe_end:
  548.   *ab_area= loc_ab_area;
  549.   return loc_ab_area - a_area;
  550. }
  551. #define RT_PERIM_INC_KORR(type, korr_func, len) 
  552.    type amin, amax, bmin, bmax; 
  553.    amin = korr_func(a); 
  554.    bmin = korr_func(b); 
  555.    amax = korr_func(a+len); 
  556.    bmax = korr_func(b+len); 
  557.    a_perim+= (((double)amax) - ((double)amin)); 
  558.    *ab_perim+= ((double)max(amax, bmax) - (double)min(amin, bmin)); 
  559. }
  560. #define RT_PERIM_INC_GET(type, get_func, len)
  561. {
  562.    type amin, amax, bmin, bmax; 
  563.    get_func(amin, a); 
  564.    get_func(bmin, b); 
  565.    get_func(amax, a+len); 
  566.    get_func(bmax, b+len); 
  567.    a_perim+= (((double)amax) - ((double)amin)); 
  568.    *ab_perim+= ((double)max(amax, bmax) - (double)min(amin, bmin)); 
  569. }
  570. /*
  571. Calculates MBR_PERIMETER(a+b) - MBR_PERIMETER(a)
  572. */
  573. double rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b, 
  574. uint key_length, double *ab_perim)
  575. {
  576.   double a_perim = 0.0;
  577.   
  578.   *ab_perim= 0.0;
  579.   for (; (int)key_length > 0; keyseg += 2)
  580.   {
  581.     uint32 keyseg_length;
  582.     if (keyseg->null_bit)                       /* Handle NULL part */
  583.       return -1;
  584.     switch ((enum ha_base_keytype) keyseg->type) {
  585.     case HA_KEYTYPE_INT8:
  586.       RT_PERIM_INC_KORR(int8, mi_sint1korr, 1);
  587.       break;
  588.     case HA_KEYTYPE_BINARY:
  589.       RT_PERIM_INC_KORR(uint8, mi_uint1korr, 1);
  590.       break;
  591.     case HA_KEYTYPE_SHORT_INT:
  592.       RT_PERIM_INC_KORR(int16, mi_sint2korr, 2);
  593.       break;
  594.     case HA_KEYTYPE_USHORT_INT:
  595.       RT_PERIM_INC_KORR(uint16, mi_uint2korr, 2);
  596.       break;
  597.     case HA_KEYTYPE_INT24:
  598.       RT_PERIM_INC_KORR(int32, mi_sint3korr, 3);
  599.       break;
  600.     case HA_KEYTYPE_UINT24:
  601.       RT_PERIM_INC_KORR(int32, mi_uint3korr, 3);
  602.       break;
  603.     case HA_KEYTYPE_LONG_INT:
  604.       RT_PERIM_INC_KORR(int32, mi_sint4korr, 4);
  605.       break;
  606.     case HA_KEYTYPE_ULONG_INT:
  607.       RT_PERIM_INC_KORR(uint32, mi_uint4korr, 4);
  608.       break;
  609. #ifdef HAVE_LONG_LONG
  610.     case HA_KEYTYPE_LONGLONG:
  611.       RT_PERIM_INC_KORR(longlong, mi_sint8korr, 8);
  612.       break;
  613.     case HA_KEYTYPE_ULONGLONG:
  614.       RT_PERIM_INC_KORR(longlong, mi_sint8korr, 8);
  615.       break;
  616. #endif
  617.     case HA_KEYTYPE_FLOAT:
  618.       RT_PERIM_INC_GET(float, mi_float4get, 4);
  619.       break;
  620.     case HA_KEYTYPE_DOUBLE:
  621.       RT_PERIM_INC_GET(double, mi_float8get, 8);
  622.       break;
  623.     case HA_KEYTYPE_END:
  624.       return *ab_perim - a_perim;
  625.     default:
  626.       return -1;
  627.     }
  628.     keyseg_length= keyseg->length * 2;
  629.     key_length-= keyseg_length;
  630.     a+= keyseg_length;
  631.     b+= keyseg_length;
  632.   }
  633.   return *ab_perim - a_perim;
  634. }
  635. #define RT_PAGE_MBR_KORR(type, korr_func, store_func, len) 
  636.   type amin, amax, bmin, bmax; 
  637.   amin = korr_func(k + inc); 
  638.   amax = korr_func(k + inc + len); 
  639.   k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); 
  640.   for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) 
  641.     bmin = korr_func(k + inc); 
  642.     bmax = korr_func(k + inc + len); 
  643.     if (amin > bmin) 
  644.       amin = bmin; 
  645.     if (amax < bmax) 
  646.       amax = bmax; 
  647.   store_func(c, amin); 
  648.   c += len; 
  649.   store_func(c, amax); 
  650.   c += len; 
  651.   inc += 2 * len; 
  652. }
  653. #define RT_PAGE_MBR_GET(type, get_func, store_func, len) 
  654.   type amin, amax, bmin, bmax; 
  655.   get_func(amin, k + inc); 
  656.   get_func(amax, k + inc + len); 
  657.   k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag); 
  658.   for (; k < last; k = rt_PAGE_NEXT_KEY(k, k_len, nod_flag)) 
  659.     get_func(bmin, k + inc); 
  660.     get_func(bmax, k + inc + len); 
  661.     if (amin > bmin) 
  662.       amin = bmin; 
  663.     if (amax < bmax) 
  664.       amax = bmax; 
  665.   store_func(c, amin); 
  666.   c += len; 
  667.   store_func(c, amax); 
  668.   c += len; 
  669.   inc += 2 * len; 
  670. }
  671. /*
  672. Calculates key page total MBR = MBR(key1) + MBR(key2) + ...
  673. */
  674. int rtree_page_mbr(MI_INFO *info, HA_KEYSEG *keyseg, uchar *page_buf,
  675.                   uchar *c, uint key_length)
  676. {
  677.   uint inc = 0;
  678.   uint k_len = key_length;
  679.   uint nod_flag = mi_test_if_nod(page_buf);
  680.   uchar *k;
  681.   uchar *last = rt_PAGE_END(page_buf);
  682.   for (; (int)key_length > 0; keyseg += 2)
  683.   {
  684.     key_length -= keyseg->length * 2;
  685.     
  686.     /* Handle NULL part */
  687.     if (keyseg->null_bit)
  688.     {
  689.       return 1;
  690.     }
  691.     k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
  692.     switch ((enum ha_base_keytype) keyseg->type) {
  693.     case HA_KEYTYPE_INT8:
  694.       RT_PAGE_MBR_KORR(int8, mi_sint1korr, mi_int1store, 1);
  695.       break;
  696.     case HA_KEYTYPE_BINARY:
  697.       RT_PAGE_MBR_KORR(uint8, mi_uint1korr, mi_int1store, 1);
  698.       break;
  699.     case HA_KEYTYPE_SHORT_INT:
  700.       RT_PAGE_MBR_KORR(int16, mi_sint2korr, mi_int2store, 2);
  701.       break;
  702.     case HA_KEYTYPE_USHORT_INT:
  703.       RT_PAGE_MBR_KORR(uint16, mi_uint2korr, mi_int2store, 2);
  704.       break;
  705.     case HA_KEYTYPE_INT24:
  706.       RT_PAGE_MBR_KORR(int32, mi_sint3korr, mi_int3store, 3);
  707.       break;
  708.     case HA_KEYTYPE_UINT24:
  709.       RT_PAGE_MBR_KORR(uint32, mi_uint3korr, mi_int3store, 3);
  710.       break;
  711.     case HA_KEYTYPE_LONG_INT:
  712.       RT_PAGE_MBR_KORR(int32, mi_sint4korr, mi_int4store, 4);
  713.       break;
  714.     case HA_KEYTYPE_ULONG_INT:
  715.       RT_PAGE_MBR_KORR(uint32, mi_uint4korr, mi_int4store, 4);
  716.       break;
  717. #ifdef HAVE_LONG_LONG
  718.     case HA_KEYTYPE_LONGLONG:
  719.       RT_PAGE_MBR_KORR(longlong, mi_sint8korr, mi_int8store, 8);
  720.       break;
  721.     case HA_KEYTYPE_ULONGLONG:
  722.       RT_PAGE_MBR_KORR(ulonglong, mi_uint8korr, mi_int8store, 8);
  723.       break;
  724. #endif
  725.     case HA_KEYTYPE_FLOAT:
  726.       RT_PAGE_MBR_GET(float, mi_float4get, mi_float4store, 4);
  727.       break;
  728.     case HA_KEYTYPE_DOUBLE:
  729.       RT_PAGE_MBR_GET(double, mi_float8get, mi_float8store, 8);
  730.       break;
  731.     case HA_KEYTYPE_END:
  732.       return 0;
  733.     default:
  734.       return 1;
  735.     }
  736.   }
  737.   return 0;
  738. }
  739. #endif /*HAVE_RTREE_KEYS*/