Example #1
0
vector<float> tridag(const vector<float> &a,const vector<float> &b, const vector<float> &c, const vector<float> &r)
{
    vector<float> u(b.size(),0.0);
    vector<float> gam(b.size());
    float bet;

    if(FCMP(b[0],0.0))
    {
        cout << "Error - matrix[0][0] == 0.0 - try rewriting eqns. as a set of order n-1 with u2 trivually elimianted..." << endl;
        return u;
    }

    u[0] = r[0]/(bet=b[0]);
    for(unsigned long int j = 1; j<b.size(); j++)
    {
        gam[j] = c[j-1]/bet;
        bet = b[j]-a[j]*gam[j];
        if(FCMP(bet,0.0))
        {
            cout << "Error -  cannot solve tridag system.\n" << endl;
            return u;
        }
        u[j] = (r[j]-a[j]*u[j-1])/bet;
    }
    for(unsigned long int i = b.size()-2; i>=0;i--)
    {
        u[i]-=gam[i+1]*u[i+1];
        if(i==0)
        {
            break;
        }
    }
    return u;
}
Example #2
0
int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
{
	if (spells[spell_id].not_extendable)
		return duration;

	int increase = 100;
	increase += GetFocusEffect(focusSpellDuration, spell_id);
	int tic_inc = 0;
	tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id);

	float focused = ((duration * increase) / 100.0f) + tic_inc;
	int ifocused = static_cast<int>(focused);

	// 7.6 is rounded to 7, 8.6 is rounded to 9
	// 6 is 6, etc
	if (FCMP(focused, ifocused) || ifocused % 2) // equal or odd
		return ifocused;
	else // even and not equal round to odd
		return ifocused + 1;
}
Example #3
0
Vec4 Dielectric::render(const std::vector<zyk::Object*>&p_objects, const Intersection_Info& inter_info,
	const Vec3& ray_dir, int depth, float input_rei)
{
	float ioRei[2] = { input_rei, rei };
	if (FCMP(ioRei[0], ioRei[1]) && ioRei[0]>1.0f)// the ray is leaving out the dielectric
		ioRei[1] = 1.0f;

	Vec3 refra_dir;
	Vec4 shade_color;
	float ref_weight, refra_weight;
	bool is_refract = refractRay(inter_info.inter_pt, ray_dir,inter_info.inter_nor, ioRei, refra_dir, ref_weight);
	if (is_refract)
	{
		float out_rei = ioRei[1];
		shade_color = g_pGlobalSys->castRayShading_McSampling(p_objects,
			InputRay(inter_info.inter_pt + refra_dir*0.01, refra_dir),depth + 1, out_rei);
	}
	else
		shade_color = Vec4(0,0,0,1);
	return shade_color;
}
Example #4
0
void FloatMatrix::LUBackSubstitute( vector<float> &b )
{
    unsigned long int ip;
    long int ii = -1;
    float sum;

    for(unsigned long int i = 0; i<b.size(); i++)
    {
        ip = row_perm[i];        
        sum = b[ip];         
        b[ip] = b[i];  
        
        if(ii>-1)
        {
            //printf("ii not zero (=%d, with i = %d)...\n",ii,i);
            for(unsigned long int j = ii; j<=i-1;j++)
            {
                //printf("...(ii=true), subtracting a[%d][%d]*b[%d] (=%f/%f = %f) from sum (currently %f)...\n",i,j,j,(*this)(i,j),b[j],(*this)(i,j)/b[j],sum);
                sum-=(*this)(i,j)*b[j];
                //printf("..and now sum is %f\n",sum);
            }
        }
        else if(!FCMP(sum,0.0))
        {
            //printf("sum not zero (=%f), with i = %d\n",sum,i);
            ii =i;
        }
        b[i] = sum;        
    }
    for(long int k = b.size()-1;k>=0;k--)
    {        
        sum = b[k];        
        for(unsigned long int j = k+1;j<b.size();j++)
        {            
            sum-=(*this)(k,j)*b[j];
        }        
        b[k] = sum/(*this)(k,k);
    }    
}
Example #5
0
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
	       register uchar *b, uint key_length, uint nextflag,
	       uint *diff_pos)
{
  int flag;
  int16 s_1,s_2;
  int32 l_1,l_2;
  uint32 u_1,u_2;
  float f_1,f_2;
  double d_1,d_2;
  uint next_key_length;
  uchar *orig_b= b;

  *diff_pos=0;
  for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
  {
    uchar *end;
    uint piks=! (keyseg->flag & HA_NO_SORT);
    (*diff_pos)++;
    diff_pos[1]= (uint)(b - orig_b);

    /* Handle NULL part */
    if (keyseg->null_bit)
    {
      key_length--;
      if (*a != *b && piks)
      {
        flag = (int) *a - (int) *b;
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      }
      b++;
      if (!*a++)                                /* If key was NULL */
      {
        if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
          nextflag=SEARCH_SAME;                 /* Allow duplicate keys */
  	else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
	{
	  /*
	    This is only used from mi_check() to calculate cardinality.
	    It can't be used when searching for a key as this would cause
	    compare of (a,b) and (b,a) to return the same value.
	  */
	  return -1;
	}
        next_key_length=key_length;
        continue;                               /* To next key part */
      }
    }
    end= a+ min(keyseg->length,key_length);
    next_key_length=key_length-keyseg->length;

    switch ((enum ha_base_keytype) keyseg->type) {
    case HA_KEYTYPE_TEXT:                       /* Ascii; Key is converted */
      if (keyseg->flag & HA_SPACE_PACK)
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
            (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
				  (my_bool) ((nextflag & SEARCH_PREFIX) &&
					     next_key_length <= 0),
				  (my_bool)!(nextflag & SEARCH_PREFIX))))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=a_length;
        b+=b_length;
        break;
      }
      else
      {
	uint length=(uint) (end-a), a_length=length, b_length=length;
        if (piks &&
            (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
				   (my_bool) ((nextflag & SEARCH_PREFIX) &&
					      next_key_length <= 0),
				   (my_bool)!(nextflag & SEARCH_PREFIX))))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a=end;
        b+=length;
      }
      break;
    case HA_KEYTYPE_BINARY:
    case HA_KEYTYPE_BIT:
      if (keyseg->flag & HA_SPACE_PACK)
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
	    (flag=compare_bin(a,a_length,b,b_length,
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                         next_key_length <= 0),1)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=a_length;
        b+=b_length;
        break;
      }
      else
      {
        uint length=keyseg->length;
        if (piks &&
	    (flag=compare_bin(a,length,b,length,
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                         next_key_length <= 0),0)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=length;
        b+=length;
      }
      break;
    case HA_KEYTYPE_VARTEXT1:
    case HA_KEYTYPE_VARTEXT2:
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
	    (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                              next_key_length <= 0),
				   (my_bool) ((nextflag & (SEARCH_FIND |
							   SEARCH_UPDATE)) ==
					      SEARCH_FIND &&
                                              ! (keyseg->flag &
                                                 HA_END_SPACE_ARE_EQUAL)))))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+= a_length;
        b+= b_length;
        break;
      }
      break;
    case HA_KEYTYPE_VARBINARY1:
    case HA_KEYTYPE_VARBINARY2:
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
	    (flag=compare_bin(a,a_length,b,b_length,
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                         next_key_length <= 0), 0)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=a_length;
        b+=b_length;
      }
      break;
    case HA_KEYTYPE_INT8:
    {
      int i_1= (int) *((signed char*) a);
      int i_2= (int) *((signed char*) b);
      if (piks && (flag = CMP_NUM(i_1,i_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a= end;
      b++;
      break;
    }
    case HA_KEYTYPE_SHORT_INT:
      s_1= mi_sint2korr(a);
      s_2= mi_sint2korr(b);
      if (piks && (flag = CMP_NUM(s_1,s_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 2; /* sizeof(short int); */
      break;
    case HA_KEYTYPE_USHORT_INT:
      {
        uint16 us_1,us_2;
        us_1= mi_sint2korr(a);
        us_2= mi_sint2korr(b);
        if (piks && (flag = CMP_NUM(us_1,us_2)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a=  end;
        b+=2; /* sizeof(short int); */
        break;
      }
    case HA_KEYTYPE_LONG_INT:
      l_1= mi_sint4korr(a);
      l_2= mi_sint4korr(b);
      if (piks && (flag = CMP_NUM(l_1,l_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 4; /* sizeof(long int); */
      break;
    case HA_KEYTYPE_ULONG_INT:
      u_1= mi_sint4korr(a);
      u_2= mi_sint4korr(b);
      if (piks && (flag = CMP_NUM(u_1,u_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 4; /* sizeof(long int); */
      break;
    case HA_KEYTYPE_INT24:
      l_1=mi_sint3korr(a);
      l_2=mi_sint3korr(b);
      if (piks && (flag = CMP_NUM(l_1,l_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 3;
      break;
    case HA_KEYTYPE_UINT24:
      l_1=mi_uint3korr(a);
      l_2=mi_uint3korr(b);
      if (piks && (flag = CMP_NUM(l_1,l_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 3;
      break;
    case HA_KEYTYPE_FLOAT:
      mi_float4get(f_1,a);
      mi_float4get(f_2,b);
      /*
        The following may give a compiler warning about floating point
        comparison not being safe, but this is ok in this context as
        we are bascily doing sorting
      */
      if (piks && (flag = CMP_NUM(f_1,f_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 4; /* sizeof(float); */
      break;
    case HA_KEYTYPE_DOUBLE:
      mi_float8get(d_1,a);
      mi_float8get(d_2,b);
      /*
        The following may give a compiler warning about floating point
        comparison not being safe, but this is ok in this context as
        we are bascily doing sorting
      */
      if (piks && (flag = CMP_NUM(d_1,d_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 8;  /* sizeof(double); */
      break;
    case HA_KEYTYPE_NUM:                                /* Numeric key */
    {
      int swap_flag= 0;
      int alength,blength;

      if (keyseg->flag & HA_REVERSE_SORT)
      {
        swap_variables(uchar*, a, b);
        swap_flag=1;                            /* Remember swap of a & b */
        end= a+ (int) (end-b);
      }
      if (keyseg->flag & HA_SPACE_PACK)
      {
        alength= *a++; blength= *b++;
        end=a+alength;
        next_key_length=key_length-blength-1;
      }
      else
      {
        alength= (int) (end-a);
        blength=keyseg->length;
        /* remove pre space from keys */
        for ( ; alength && *a == ' ' ; a++, alength--) ;
        for ( ; blength && *b == ' ' ; b++, blength--) ;
      }
      if (piks)
      {
	if (*a == '-')
	{
	  if (*b != '-')
	    return -1;
	  a++; b++;
	  swap_variables(uchar*, a, b);
	  swap_variables(int, alength, blength);
	  swap_flag=1-swap_flag;
	  alength--; blength--;
	  end=a+alength;
	}
	else if (*b == '-')
	  return 1;
	while (alength && (*a == '+' || *a == '0'))
	{
	  a++; alength--;
	}
	while (blength && (*b == '+' || *b == '0'))
	{
	  b++; blength--;
	}
	if (alength != blength)
	  return (alength < blength) ? -1 : 1;
	while (a < end)
	  if (*a++ !=  *b++)
	    return ((int) a[-1] - (int) b[-1]);
      }
      else
      {
        b+=(end-a);
        a=end;
      }

      if (swap_flag)                            /* Restore pointers */
        swap_variables(uchar*, a, b);
      break;
    }
#ifdef HAVE_LONG_LONG
    case HA_KEYTYPE_LONGLONG:
    {
      longlong ll_a,ll_b;
      ll_a= mi_sint8korr(a);
      ll_b= mi_sint8korr(b);
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 8;
      break;
    }
    case HA_KEYTYPE_ULONGLONG:
    {
      ulonglong ll_a,ll_b;
      ll_a= mi_uint8korr(a);
      ll_b= mi_uint8korr(b);
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 8;
      break;
    }
#endif
    case HA_KEYTYPE_END:                        /* Ready */
      goto end;                                 /* diff_pos is incremented */
    }
  }
  (*diff_pos)++;
end:
  if (!(nextflag & SEARCH_FIND))
  {
    uint i;
    if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
      return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
    flag=0;
    for (i=keyseg->length ; i-- > 0 ; )
    {
      if (*a++ != *b++)
      {
        flag= FCMP(a[-1],b[-1]);
        break;
      }
    }
    if (nextflag & SEARCH_SAME)
      return (flag);                            /* read same */
    if (nextflag & SEARCH_BIGGER)
      return (flag <= 0 ? -1 : 1);              /* read next */
    return (flag < 0 ? -1 : 1);                 /* read previous */
  }
  return 0;
} /* ha_key_cmp */
Example #6
0
void GaussElimLinearSolve(FloatMatrix &a, FloatMatrix &x, FloatMatrix &b)
{    

    if( (a.rows() != x.rows()) || (a.rows() != b.rows()) || (b.rows() != x.rows()) )
    {
        cout << "Can't solve - not all matrices in " << a.rows() << " equations." << endl;        
    }    

    float pvt;                   
    vector<unsigned long int> pivot(a.rows());
    unsigned long int ipvt_store;

    for(unsigned long int j = 0; j < a.rows()-1; j++)//step over all the (columns?) from the first to the last but 1
    {
        pvt = fabs(a(j,j));//initialise pivot point to a(0,0)
        pivot[j] = j;
        ipvt_store = j+1;

        for(unsigned long int i = j + 1; i < a.rows(); i++)
        {//now find pivot row (if its not the first one)
         //(the loop statement above has the effect of stepping down the 
         //jth column)
            
            if(fabs(a(i,j)) > pvt)//if value at the ith row of this column is > than the current pivot value....
            {
                pvt = fabs(a(i,j));//set the pivot value to the new value
                ipvt_store = i;//?
            }
        }

        if(pivot[j] != ipvt_store)
        {
            float temp;
            pivot[j] = ipvt_store;
            pivot[ipvt_store] = j;

            for(unsigned long int k = 0; k < a.rows(); k++)
            {
                temp = a(j,k);
                a(j,k) = a(pivot[j],k);
                a(pivot[j],k) = temp;
            }

            //for multiple right hand sides... otherwise l just == 0
            for(unsigned long int l = 0; l < b.cols(); l++)
            {

                temp = b(j,l);
                b(j,l) = b(pivot[j],l);
                b(pivot[j],l) = temp;
            }      
        }

        if(FCMP(a(j,j),0.0))
        {
            cout << "Error - singular matrix encountered, no solution." << endl;            
        }

        for(unsigned long int l = j+1; l < a.rows(); l++)
        {//store multipliers
            a(l,j)/=a(j,j);
        }

        for(unsigned long int m = j+1; m < a.rows(); m++)
        {//create zeros below main diagonals
            for(unsigned long int n = j+1; n < a.rows(); n++)
            {
                a(m,n)-=(a(m,j)*a(j,n));
            }

            for(unsigned long int o = 0; o < b.cols(); o++)
            {
                b(m,o)-=(a(m,j)*b(j,o));
            }            
        }        
    }
    //now for baclk substition
    for(unsigned long int n = 0; n<x.cols(); n++)
    {
        x(a.rows()-1,n) = b(a.rows()-1,n)/a(a.rows()-1,a.rows()-1);
    }       

    for(unsigned long int i = a.rows()-2; i >= 0; i--)
    {        
        if(FCMP(a(i,i),0.0))
        {
            cout << "Error - singular matrix encountered, no solution." << endl;
            cout << "a(" << i << "," << i << ") is " << a(i,i) << ")" << endl;        
        }

        for(unsigned  int p = 0; p < b.cols(); p++)
        {
            x(i,p) = b(i,p);

            for(unsigned int k = a.rows()-1; k >= i+1; k--)
            {           
                x(i,p)-=(x(k,p)*a(i,k));
            }

            x(i,p)/=a(i,i);
        }       

        if(i == 0)//unsigned - dcrenmemnting after 0 just give smax _unsigned_ value, not <0!
        {
            break;
        }
    }

    //cout << "a is:" << endl << a << endl;
    //cout << "b is:" << endl << b << endl;
    //cout << "x is:" << endl << x << endl;        
}
Example #7
0
void FloatMatrix::LUDecompose()
{
    //Performs LUDecomposition of this matrix, replacing it with its 
    //LU decomposition
    if(rows()!=cols())
    {
        cout << "Error - square matrix requried fro LUDecompose()." << endl;
        return;
    }
    d = 1.0;            
    vector<float> vv(cols());
    float big,temp,sum,dum;
    unsigned int imax;
    for(unsigned int i = 0; i<rows(); i++)//loop over rows to get implicit scaling information
    {
        big = 0.0;
        for(unsigned int j = 0; j<cols();j++)
        {            
            if((temp = fabs((*this)(i,j))) > big)
            {         
                big = temp;
            }
        }

        if(FCMP(big,0.0))
        {            
            return;
        }    
        
        vv[i] = 1.0/big;//save the scaling        
    }    

    for(unsigned int j = 0; j < cols();j++)//this is the loop over columsn of Crout's method
    {
        for(unsigned int i = 0; i<j; i++)//now do eqn 2.3.12 of Press et al (p44) (excpt for i = j)
        {                 
            sum = (*this)(i,j);
            for(unsigned int k =0; k<i;k++)
            {                
                sum -= (*this)(i,k) * (*this)(k,j);             
            }            
            (*this)(i,j) = sum;            
        }
        big = 0.0;//initialise the search for the largest pivot element
        
        for(unsigned int q= j; q<rows();q++)//this is i = j of eqn. 2.3.12 of Press et al (p.44)
        {                                    //and i = j+1...N of 2.3.13         
            sum = (*this)(q,j);
            for(unsigned int k = 0; k<j;k++)
            {   
                sum -= (*this)(q,k)*(*this)(k,j);             
            }
            (*this)(q,j) = sum;
            
            if( (dum = vv[q]*fabs(sum)) >= big)
            {            
                big = dum;
                imax = q;             
            }            
        }
        
        if(j != imax)//do rows need interchanging?
        {//Yes! Do it.        
            for(unsigned int k = 0; k<rows();k++)
            {                
                dum = (*this)(imax,k);             
                (*this)(imax,k) = (*this)(j,k);                
                (*this)(j,k) = dum;
            }
            
            d=-d;//row interchange - change sign of d
            
            vv[imax] = vv[j];//interchange the scale factor
            
        }        
        
        row_perm[j]= imax;

        if(  FCMP( (*this)(j,j),0.0 ) )
        {
            cout << "Error - pivot element is 0!" << endl << "Matrix is singular and only partly LUDecomposed." << endl;
            return;
        }        
        if(j != rows()-1)//finally, divide by the pivot element
        {            
            dum = 1.0/((*this)(j,j));
            for(unsigned int i = j+1; i<rows(); i++)
            {         
                (*this)(i,j)*=dum;
            }
        }             
    }    
}
Example #8
0
/*
 Compares two keys a and b depending on nextflag
 nextflag can contain these flags:
   MBR_INTERSECT(a,b)  a overlaps b
   MBR_CONTAIN(a,b)    a contains b
   MBR_DISJOINT(a,b)   a disjoint b
   MBR_WITHIN(a,b)     a within   b
   MBR_EQUAL(a,b)      All coordinates of MBRs are equal
   MBR_DATA(a,b)       Data reference is the same
 Returns 0 on success.
*/
int rtree_key_cmp(HA_KEYSEG *keyseg, uchar *b, uchar *a, uint key_length, 
                  uint nextflag)
{
  for (; (int) key_length > 0; keyseg += 2 )
  {
    uint32 keyseg_length;
    switch ((enum ha_base_keytype) keyseg->type) {
    case HA_KEYTYPE_INT8:
      RT_CMP_KORR(int8, mi_sint1korr, 1, nextflag);
      break;
    case HA_KEYTYPE_BINARY:
      RT_CMP_KORR(uint8, mi_uint1korr, 1, nextflag);
      break;
    case HA_KEYTYPE_SHORT_INT:
      RT_CMP_KORR(int16, mi_sint2korr, 2, nextflag);
      break;
    case HA_KEYTYPE_USHORT_INT:
      RT_CMP_KORR(uint16, mi_uint2korr, 2, nextflag);
      break;
    case HA_KEYTYPE_INT24:
      RT_CMP_KORR(int32, mi_sint3korr, 3, nextflag);
      break;
    case HA_KEYTYPE_UINT24:
      RT_CMP_KORR(uint32, mi_uint3korr, 3, nextflag);
      break;
    case HA_KEYTYPE_LONG_INT:
      RT_CMP_KORR(int32, mi_sint4korr, 4, nextflag);
      break;
    case HA_KEYTYPE_ULONG_INT:
      RT_CMP_KORR(uint32, mi_uint4korr, 4, nextflag);
      break;
#ifdef HAVE_LONG_LONG
    case HA_KEYTYPE_LONGLONG:
      RT_CMP_KORR(longlong, mi_sint8korr, 8, nextflag)
      break;
    case HA_KEYTYPE_ULONGLONG:
      RT_CMP_KORR(ulonglong, mi_uint8korr, 8, nextflag)
      break;
#endif
    case HA_KEYTYPE_FLOAT:
      /* The following should be safe, even if we compare doubles */
      RT_CMP_GET(float, mi_float4get, 4, nextflag);
      break;
    case HA_KEYTYPE_DOUBLE:
      RT_CMP_GET(double, mi_float8get, 8, nextflag);
      break;
    case HA_KEYTYPE_END:
      goto end;
    default:
      return 1;
    }
    keyseg_length= keyseg->length * 2;
    key_length-= keyseg_length;
    a+= keyseg_length;
    b+= keyseg_length;
  }

end:
  if (nextflag & MBR_DATA)
  {
    uchar *end = a + keyseg->length;
    do
    {
      if (*a++ != *b++)
        return FCMP(a[-1], b[-1]);
    } while (a != end);
  }
  return 0;
}
int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a,
               const uchar *b, uint key_length, uint32 nextflag,
	       uint *diff_pos)
{
  int flag;
  int16 s_1,s_2;
  int32 l_1,l_2;
  uint32 u_1,u_2;
  float f_1,f_2;
  double d_1,d_2;
  uint next_key_length;
  const uchar *orig_b= b;

  *diff_pos=0;
  for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
  {
    const uchar *end;
    uint piks=! (keyseg->flag & HA_NO_SORT);
    (*diff_pos)++;
    diff_pos[1]= (uint)(b - orig_b);

    /* Handle NULL part */
    if (keyseg->null_bit)
    {
      key_length--;
      if (*a != *b && piks)
      {
        flag = (int) *a - (int) *b;
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      }
      b++;
      if (!*a++)                                /* If key was NULL */
      {
        if ((nextflag & (SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT |
                         SEARCH_NULL_ARE_EQUAL)) ==
            (SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT))
        {
          /* Allow duplicate keys */
          nextflag= (nextflag & ~(SEARCH_FIND | SEARCH_UPDATE)) | SEARCH_SAME;
        }
  	else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
	{
	  /*
	    This is only used from mi_check() to calculate cardinality.
	    It can't be used when searching for a key as this would cause
	    compare of (a,b) and (b,a) to return the same value.
	  */
	  return -1;
	}
        next_key_length=key_length;
        continue;                               /* To next key part */
      }
    }
    end= a+ MY_MIN(keyseg->length,key_length);
    next_key_length=key_length-keyseg->length;

    switch ((enum ha_base_keytype) keyseg->type) {
    case HA_KEYTYPE_TEXT:                       /* Ascii; Key is converted */
      if (keyseg->flag & HA_SPACE_PACK)
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
            (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
				  (my_bool) ((nextflag & SEARCH_PREFIX) &&
					     next_key_length <= 0),
				  (my_bool)!(nextflag & SEARCH_PREFIX))))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=a_length;
        b+=b_length;
        break;
      }
      else
      {
	uint length=(uint) (end-a), a_length=length, b_length=length;
        if (piks &&
            (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
				   (my_bool) ((nextflag & SEARCH_PREFIX) &&
					      next_key_length <= 0),
				   (my_bool)!(nextflag & SEARCH_PREFIX))))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a=end;
        b+=length;
      }
      break;
    case HA_KEYTYPE_BINARY:
    case HA_KEYTYPE_BIT:
      if (keyseg->flag & HA_SPACE_PACK)
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
	    (flag=compare_bin(a,a_length,b,b_length,
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                         next_key_length <= 0),1)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=a_length;
        b+=b_length;
        break;
      }
      else
      {
        uint length=keyseg->length;
        if (piks &&
	    (flag=compare_bin(a,length,b,length,
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                         next_key_length <= 0),0)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=length;
        b+=length;
      }
      break;
    case HA_KEYTYPE_VARTEXT1:
    case HA_KEYTYPE_VARTEXT2:
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
	    (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                              next_key_length <= 0),
				   (my_bool) ((nextflag & (SEARCH_FIND |
							   SEARCH_UPDATE)) ==
					      SEARCH_FIND &&
                                              ! (keyseg->flag &
                                                 HA_END_SPACE_ARE_EQUAL)))))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+= a_length;
        b+= b_length;
        break;
      }
      break;
    case HA_KEYTYPE_VARBINARY1:
    case HA_KEYTYPE_VARBINARY2:
      {
        int a_length,b_length,pack_length;
        get_key_length(a_length,a);
        get_key_pack_length(b_length,pack_length,b);
        next_key_length=key_length-b_length-pack_length;

        if (piks &&
	    (flag=compare_bin(a,a_length,b,b_length,
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
                                         next_key_length <= 0), 0)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a+=a_length;
        b+=b_length;
      }
      break;
    case HA_KEYTYPE_INT8:
    {
      int i_1= (int) *((signed char*) a);
      int i_2= (int) *((signed char*) b);
      if (piks && (flag = CMP_NUM(i_1,i_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a= end;
      b++;
      break;
    }
    case HA_KEYTYPE_SHORT_INT:
      s_1= mi_sint2korr(a);
      s_2= mi_sint2korr(b);
      if (piks && (flag = CMP_NUM(s_1,s_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 2; /* sizeof(short int); */
      break;
    case HA_KEYTYPE_USHORT_INT:
      {
        uint16 us_1,us_2;
        us_1= mi_sint2korr(a);
        us_2= mi_sint2korr(b);
        if (piks && (flag = CMP_NUM(us_1,us_2)))
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
        a=  end;
        b+=2; /* sizeof(short int); */
        break;
      }
    case HA_KEYTYPE_LONG_INT:
      l_1= mi_sint4korr(a);
      l_2= mi_sint4korr(b);
      if (piks && (flag = CMP_NUM(l_1,l_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 4; /* sizeof(long int); */
      break;
    case HA_KEYTYPE_ULONG_INT:
      u_1= mi_sint4korr(a);
      u_2= mi_sint4korr(b);
      if (piks && (flag = CMP_NUM(u_1,u_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 4; /* sizeof(long int); */
      break;
    case HA_KEYTYPE_INT24:
      l_1=mi_sint3korr(a);
      l_2=mi_sint3korr(b);
      if (piks && (flag = CMP_NUM(l_1,l_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 3;
      break;
    case HA_KEYTYPE_UINT24:
      l_1=mi_uint3korr(a);
      l_2=mi_uint3korr(b);
      if (piks && (flag = CMP_NUM(l_1,l_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 3;
      break;
    case HA_KEYTYPE_FLOAT:
      mi_float4get(f_1,a);
      mi_float4get(f_2,b);
      /*
        The following may give a compiler warning about floating point
        comparison not being safe, but this is ok in this context as
        we are bascily doing sorting
      */
      if (piks && (flag = CMP_NUM(f_1,f_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 4; /* sizeof(float); */
      break;
    case HA_KEYTYPE_DOUBLE:
      mi_float8get(d_1,a);
      mi_float8get(d_2,b);
      /*
        The following may give a compiler warning about floating point
        comparison not being safe, but this is ok in this context as
        we are bascily doing sorting
      */
      if (piks && (flag = CMP_NUM(d_1,d_2)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 8;  /* sizeof(double); */
      break;
    case HA_KEYTYPE_NUM:                                /* Numeric key */
    {
      int swap_flag= 0;
      int alength,blength;

      if (keyseg->flag & HA_REVERSE_SORT)
      {
        swap_variables(const uchar*, a, b);
        swap_flag=1;                            /* Remember swap of a & b */
        end= a+ (int) (end-b);
      }
      if (keyseg->flag & HA_SPACE_PACK)
      {
        alength= *a++; blength= *b++;
        end=a+alength;
        next_key_length=key_length-blength-1;
      }
      else
      {
        alength= (int) (end-a);
        blength=keyseg->length;
        /* remove pre space from keys */
        for ( ; alength && *a == ' ' ; a++, alength--) ;
        for ( ; blength && *b == ' ' ; b++, blength--) ;
      }
      if (piks)
      {
	if (*a == '-')
	{
	  if (*b != '-')
	    return -1;
	  a++; b++;
	  swap_variables(const uchar*, a, b);
	  swap_variables(int, alength, blength);
	  swap_flag=1-swap_flag;
	  alength--; blength--;
	  end=a+alength;
	}
	else if (*b == '-')
	  return 1;
	while (alength && (*a == '+' || *a == '0'))
	{
	  a++; alength--;
	}
	while (blength && (*b == '+' || *b == '0'))
	{
	  b++; blength--;
	}
	if (alength != blength)
	  return (alength < blength) ? -1 : 1;
	while (a < end)
	  if (*a++ !=  *b++)
	    return ((int) a[-1] - (int) b[-1]);
      }
      else
      {
        b+=(end-a);
        a=end;
      }

      if (swap_flag)                            /* Restore pointers */
        swap_variables(const uchar*, a, b);
      break;
    }
#ifdef HAVE_LONG_LONG
    case HA_KEYTYPE_LONGLONG:
    {
      longlong ll_a,ll_b;
      ll_a= mi_sint8korr(a);
      ll_b= mi_sint8korr(b);
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 8;
      break;
    }
    case HA_KEYTYPE_ULONGLONG:
    {
      ulonglong ll_a,ll_b;
      ll_a= mi_uint8korr(a);
      ll_b= mi_uint8korr(b);
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
      a=  end;
      b+= 8;
      break;
    }
#endif
    case HA_KEYTYPE_END:                        /* Ready */
      goto end;                                 /* diff_pos is incremented */
    }
  }
  (*diff_pos)++;
end:
  if (!(nextflag & SEARCH_FIND))
  {
    /*
      Compare rowid and possible transid
      This happens in the following case:
      - INSERT, UPDATE, DELETE when we have not unique keys or
        are using versioning
      - SEARCH_NEXT, SEARCH_PREVIOUS when we need to restart search

      The logic for comparing transid are as follows:
      Keys with have a transid have lowest bit in the rowidt. This means that
      if we are comparing a key with a transid with another key that doesn't
      have a tranid, we must reset the lowest bit for both keys.

      When we have transid, the keys are compared in transid order.
      A key without a transid is regared to be smaller than a key with
      a transid.
    */

    uint i;
    uchar key_mask, tmp_a, tmp_b;

    if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
      return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
    key_mask= (uchar) 255;

    if (!(nextflag & (SEARCH_USER_KEY_HAS_TRANSID |
                      SEARCH_PAGE_KEY_HAS_TRANSID)))
    {
      /*
        Neither key has a trid.  Only compare row id's and don't
        try to store rows in trid order
      */
      key_length= keyseg->length;
      nextflag&= ~SEARCH_INSERT;
    }
    else
    {
      /*
        Set key_mask so that we reset the last bit in the rowid before
        we compare it. This is needed as the lowest bit in the rowid is
        used to mark if the key has a transid or not.
      */
      key_mask= (uchar) 254;
      if (!test_all_bits(nextflag, (SEARCH_USER_KEY_HAS_TRANSID |
                                    SEARCH_PAGE_KEY_HAS_TRANSID)))
      {
        /*
          No transaction id for user key or for key on page 
          Ignore transid as at least one of the keys are visible for all
        */
        key_length= keyseg->length;
      }
      else
      {
        /*
          Both keys have trids. No need of special handling of incomplete
          trids below.
        */
        nextflag&= ~SEARCH_INSERT;
      }
    }
    DBUG_ASSERT(key_length > 0);

    for (i= key_length-1 ; (int) i-- > 0 ; )
    {
      if (*a++ != *b++)
      {
        flag= FCMP(a[-1],b[-1]);
        goto found;
      }
    }
    tmp_a= *a & key_mask;
    tmp_b= *b & key_mask;
    flag= FCMP(tmp_a, tmp_b);

    if (flag == 0 && (nextflag & SEARCH_INSERT))
    {
      /*
        Ensure that on insert we get rows stored in trid order.
        If one of the parts doesn't have a trid, this should be regarded
        as smaller than the other
      */
        return (nextflag & SEARCH_USER_KEY_HAS_TRANSID) ? -1 : 1;
    }
found:
    if (nextflag & SEARCH_SAME)
      return (flag);                            /* read same */
    if (nextflag & SEARCH_BIGGER)
      return (flag <= 0 ? -1 : 1);              /* read next */
    return (flag < 0 ? -1 : 1);                 /* read previous */
  }
  return 0;
} /* ha_key_cmp */