Difference or multibyte unsigned value in lesser bytes

 

I'm trying to experiment with a compression scheme -that will most likely fail- .

As i can't cast a 16byte integer , (yes byte 😅) ,is there a method to do int128 A , minus int128 B ?

What this failed experiment is looking for is to know if int128 A is bigger than int128 B and if their distance is representable in less than 16bytes.

This is not important and not needed ,just playing around with code under the heat .

Thank you

 
Since the language has no such datatype, you will have to create those operations yourself.
 
William Roeder #:
Since the language has no such datatype, you will have to create those operations yourself.

yeah i'm afraid so , thanks

Work in progress so far :

#property version   "1.00"
struct bigNumberMax16{
uchar bytes[16];
int total_bytes;
      //the most significant byte must be at the end i reckon
      bigNumberMax16(void){reset();}
     ~bigNumberMax16(void){reset();}
 void reset(){
      ArrayFill(bytes,0,ArraySize(bytes),0);
      total_bytes=0;
      }
      //for testing 
 void setup_from_int(int number){
      for(int i=3;i>=0;i--){
         int y=number;
         y=y<<(8*i);
         y=y>>(24);
         add_byte((uchar)y);
         }
      } 
  int get_value(){
      //for testing again
        int result=0;
        for(int i=0;i<total_bytes;i++){
           result+=((int)bytes[i])<<(8*i);
           }
      return(result);
      }   
  int get_biggest_byte(int below_this_byte=16){
      for(int i=total_bytes-1;i>=0;i--){
      if(bytes[i]>0&&i<below_this_byte){return(i);}
      }
      return(-1);
      }    
 bool add(bigNumberMax16 &other_number){
      int max=total_bytes>=other_number.total_bytes?total_bytes:other_number.total_bytes;
      bool carry=false;
      for(int i=0;i<max;i++){
         if(i>total_bytes){if(!add_byte(0)){return(false);}}
         uchar sum_a=bytes[i];
         uchar sum_b=0;
         if(i<=other_number.total_bytes){sum_b=other_number.bytes[i];}
         uchar sum=((uchar)carry)+sum_a+sum_b;
         carry=false;
         if(sum<sum_a||sum<sum_b){carry=true;}
         bytes[i]=sum;
         if(i==(max-1)&&carry){add_byte(1);}
         }
      return(true);      
      }
 bool subtract(bigNumberMax16 &other_number){
      int max=total_bytes>=other_number.total_bytes?total_bytes:other_number.total_bytes;
      bool carry=false;
      for(int i=0;i<max;i++){
         if(i>total_bytes){if(!add_byte(0)){return(false);}}
         uchar sum_a=bytes[i];
         uchar sum_b=0;
         if(i<=other_number.total_bytes){sum_b+=other_number.bytes[i];}
         uchar sum=sum_a-sum_b-((uchar)carry);
         carry=false;
         if(sum_b>sum_a){carry=true;}
         bytes[i]=sum;
         }
      return(true);      
      }  
 void rebyte(){
      total_bytes=get_biggest_byte()+1;
      }
 bool operator>=(bigNumberMax16 &other){return(is_bigger(other)||is_equal(other));}
 bool operator>(bigNumberMax16 &other){return(is_bigger(other));}
 bool operator<=(bigNumberMax16 &other){return(is_smaller(other)||is_equal(other));}
 bool operator<(bigNumberMax16 &other){return(is_smaller(other));}
 bool operator==(bigNumberMax16 &other){return(is_equal(other));}
 bool operator!=(bigNumberMax16 &other){return(!is_equal(other));}   
      private:
 bool is_equal(bigNumberMax16 &with){
      if(total_bytes==with.total_bytes){
        bool equal=true;
        for(int i=0;i<total_bytes;i++){
           if(bytes[i]!=with.bytes[i]){ 
             equal=false;
             break;
             }
           }
        return(equal);
        }
      return(false);
      }
 bool is_bigger(bigNumberMax16 &than,int below_this_byte=16){
      int this_biggest_byte=get_biggest_byte(below_this_byte);
      int than_biggest_byte=than.get_biggest_byte(below_this_byte);
      if(this_biggest_byte>than_biggest_byte){return(true);}
      else if(this_biggest_byte==than_biggest_byte&&this_biggest_byte>-1){
           if(bytes[this_biggest_byte]>than.bytes[than_biggest_byte]){return(true);}
           else if(bytes[this_biggest_byte]==than.bytes[than_biggest_byte]){
                  return(is_bigger(than,this_biggest_byte));
                  }
           return(false);
           }
      return(false);
      }
 bool is_smaller(bigNumberMax16 &than,int below_this_byte=16){
      int this_biggest_byte=get_biggest_byte(below_this_byte);
      int than_biggest_byte=than.get_biggest_byte(below_this_byte);
      if(this_biggest_byte<than_biggest_byte){return(true);}
      else if(this_biggest_byte==than_biggest_byte&&this_biggest_byte>-1){
           if(bytes[this_biggest_byte]<than.bytes[than_biggest_byte]){return(true);}
           else if(bytes[this_biggest_byte]==than.bytes[than_biggest_byte]){
                  return(is_smaller(than,this_biggest_byte));
                  }
           return(false);
           }
      return(false);
      }      
 void set_byte(int _ix,uchar _value){
      bytes[_ix]=_value;
      }
 bool add_byte(uchar _value){
      total_bytes++;
      if(total_bytes<=16){
        bytes[total_bytes-1]=_value;
        return(true);
        }
      return(false);
      }
};

//so subtract big by small and send back info on the delta
bool subtract_bnMax16(bigNumberMax16 &a,
                      bigNumberMax16 &b,
                      bigNumberMax16 &result,
                      bool &result_negative){
  result_negative=false;
//a > b
  if(a>b){
  result=a;
  if(result.subtract(b)){
    result.rebyte();
    return(true);
    }
  return(false);
  }
//b > a
  else if(a<b){
  result=b;
  result_negative=true;
  if(result.subtract(a)){
    result.rebyte();
    return(true);
    }
  return(false);
  }
//a == b
  else{
  result.reset();
  return(true);
  }
return(false);                      
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
  bigNumberMax16 bigA,bigB,bigC;
  bigA.setup_from_int(691416);
  bigB.setup_from_int(691414);
  //lol
  Print("A("+IntegerToString(bigA.get_value())+") - B("+IntegerToString(bigB.get_value())+") = "+IntegerToString(bigA.get_value()-bigB.get_value()));
 
  //
  bool isNegative=false;
  if(subtract_bnMax16(bigA,bigB,bigC,isNegative)){
  Print("result C , bytes ("+IntegerToString(bigC.total_bytes)+")");
  Print("result C("+IntegerToString(bigC.get_value())+")");  
  }else{
  Print("Cannot do the subtraction with the methods");
  }

  return(INIT_SUCCEEDED);
  }
 
Lorentzos Roussos #:

yeah i'm afraid so , thanks

Work in progress so far :

x86 architecture is little endian...

EDIT:

As a guide, maybe:

 
Dominik Christian Egert #:
x86 architecture is little endian...

EDIT:

As a guide, maybe:

Thank you Dominik

I'm enforcing the most significant byte to be at the end of the array .

 
Lorentzos Roussos #:

Thank you Dominik

I'm enforcing the most significant byte to be at the end of the array .


Isn't that exactly the other way around to how it should be?

EDIT:

If I am not wrong, but please correct me.

Memory Address points to a location. From there you go variable size (long = 8) to the right.

Now you are at Memory Address + 8. Now you read the values between Memory Address and your current location. Least significant bit is one to the left of your current location. Sign bit is one to the right of your Memory Address.

That's how it should be.

If you take a char array, your element 0 will be your Memory Address + 1 byte. Again reading from right to left, Memory Address to Memory Address + 1 byte.

So your char array will have the sign bit in index 0 and your LSB in index 7.

Forcing it the other way around, and all registers are 64 bit anyways, will make you shift around a lot of data to process your 16 byte integer. - That seems to be very inefficient.

Anyways, isn't it so, that all you need to do is scale up the overflow of the lower 8bytes?

Even if you multiply ULONG_MAX * ULONG_MAX, you should be able to use simple operations and only need to shift between the two 8byte values accordingly?

Or am I wrong???

Edit: I know in hardware it is exactly mirrored to my description, but doesn't change the ordering.
 
Dominik Christian Egert #:

Isn't that exactly the other way around to how it should be?

EDIT:

If I am not wrong, but please correct me.

Memory Address points to a location. From there you go variable size (long = 8) to the right.

Now you are at Memory Address + 8. Now you read the values between Memory Address and your current location. Least significant bit is one to the left of your current location. Sign bit is one to the right of your Memory Address.

That's how it should be.

If you take a char array, your element 0 will be your Memory Address + 1 byte. Again reading from right to left, Memory Address to Memory Address + 1 byte.

So your char array will have the sign bit in index 0 and your LSB in index 7.

Forcing it the other way around, and all registers are 64 bit anyways, will make you shift around a lot of data to process your 16 byte integer. - That seems to be very inefficient.

Anyways, isn't it so, that all you need to do is scale up the overflow of the lower 8bytes?

Even if you multiply ULONG_MAX * ULONG_MAX, you should be able to use simple operations and only need to shift between the two 8byte values accordingly?

Or am I wrong???

Edit: I know in hardware it is exactly mirrored to my description, but doesn't change the ordering.

You are not wrong .

In the failed experiment i'm trying to perform all the "big numbers" will be unsigned , it's convenient .

Also it wont need to know the value of the bignumbers which is also convenient and why i'm testing with ints

 
Lorentzos Roussos #:

You are not wrong .

In the failed experiment i'm trying to perform all the "big numbers" will be unsigned , it's convenient .

Also it wont need to know the value of the bignumbers which is also convenient and why i'm testing with ints

But why?

Edit:
Technically there is no MSByte, only a MSBit.

You can't shift that to behave like Big Endian.

OMG. Why are you making things so complicated?
 
Dominik Christian Egert #:
But why?

Edit:
Technically there is no MSByte, only a MSBit.

You can't shift that to behave like Big Endian.

OMG. Why are you making things so complicated?

Its not going into bits either , also convenient but a weakness as well.