## digitalmars.D.learn - Problem with object understanding and datatypes

- Namal (48/48) May 24 2013 So the task is to write a struct object for the saturation
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (10/16) May 24 2013 I had a compilation error so I had to change that line to the following:
- Namal (2/4) May 24 2013 I dont understand this at all 255 - 129 should be 126 in ubyte or
- Juan Manuel Cabo (27/31) May 24 2013 I checked, and operation between two ubyte is an int. When you
- Namal (17/17) May 25 2013 Thank you very much, I thought the operators are alrdy checked by
- bearophile (4/6) May 25 2013 It looks a bit silly, I agree.
- Namal (29/35) May 25 2013 Well, now I have same Error for signed long:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (8/13) May 25 2013 According to the "Integer Literals" section here:
- Namal (1/1) May 25 2013 Thanks, that helped me alot.
- Namal (16/16) May 25 2013 I have one more question towards using unsigned datatype
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (29/37) May 25 2013 It helps a lot if you tell the error message. After making some
- =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= (2/2) Jun 23 2013 Is this code available in any repo/archive somewhere?

So the task is to write a struct object for the saturation arithmetic. I tried first to write it for the unsigned Types: struct Saturated(T) if (isIntegral!T) { static assert (isUnsigned!T || isSigned!T); property { static Saturated min() { return Saturated(T.min); } static Saturated max() { return Saturated(T.max); } static Saturated init() { return Saturated(T.init); } } Saturated opBinary(string op)(const Saturated rhs) const if (op == "+" || op == "-" || op == "/") { static if (isUnsigned!T){ if(rhs.max - rhs._value < _value) return rhs.max; if(rhs._value > _value) return rhs.min; return Saturated(cast(T)(mixin("_value " ~ op ~ " rhs._value"))); } else{ return Saturated(cast(T)(mixin("_value " ~ op ~ " rhs._value"))); } } string toString() const { import std.conv; return to!string(_value); } private: T _value; } unittest { alias subyte = Saturated!ubyte; assert(subyte(254) + subyte(2) == subyte(255)); assert(subyte(100) + subyte(2) == subyte(102)); assert(subyte(10) - subyte(11) == subyte(0)); assert(subyte(128) - subyte(129) == subyte(0)); } But the last test does not pass. Why does the minus operation is treated in signed datatype, while + is unsigned? Note that I do not know much about templates or methods. So pls execuse me if I do a major mistake here.

May 24 2013

On 05/24/2013 01:19 PM, Namal wrote:if(rhs.max - rhs._value < _value)I had a compilation error so I had to change that line to the following: if(T.max - rhs._value < _value){assert(subyte(128) - subyte(129) == subyte(0)); } But the last test does not pass.255 - 129 is less than 128 so the result is T.max, which is 255, which is not equal to 0.Why does the minus operation is treated in signed datatype, while + is unsigned?I don't think that is happening at all but the rules can get pretty confusing. See "Integer Promotions" and "Usual Arithmetic Conversions" should be known in general: :) http://dlang.org/type.html Ali

May 24 2013

255 - 129 is less than 128 so the result is T.max, which is 255, which is not equal to 0.I dont understand this at all 255 - 129 should be 126 in ubyte or not?

May 24 2013

On Saturday, 25 May 2013 at 01:03:53 UTC, Namal wrote:I checked, and operation between two ubyte is an int. When you cast that int to ubyte, it gets its least significant byte represented as ubyte. import std.stdio; void main() { ubyte x = 128; ubyte y = 129; writeln(cast(ubyte)(x - y)); //prints 255 writeln(x - y); //prints -1 writeln(typeof(x - y).stringof); //prints 'int' !!!! } Also, I tried the code you pasted, and the reason it fails the asserts is that there's something wrong in the if conditions in opBinary (and also, that 'rhs.max - rhs._value' didn't compile). The following makes your asserts pass: ... static if (op == "-") { if(_value < rhs._value) return rhs.min; } static if (op == "+") { if(_value > max._value - rhs._value) return rhs.max; } ... --jm255 - 129 is less than 128 so the result is T.max, which is 255, which is not equal to 0.I dont understand this at all 255 - 129 should be 126 in ubyte or not?

May 24 2013

Thank you very much, I thought the operators are alrdy checked by if (op == "+" || op == "-" || op == "/") But I did same tests for ushort uint and ulong, but for ulong it didn't compile. unittest{ alias sulong = Saturated!ulong; assert(sulong(18_446_744_073_709_551_610) + sulong(2) == sulong(18_446_744_073_709_551_612)); assert(sulong(18_446_744_073_709_551_614) + sulong(2) == sulong(18_446_744_073_709_551_615)); It failed to compile Error: signed integer overflow So I appended uL to each number and it worked. assert(sulong(18_446_744_073_709_551_610uL) + sulong(2uL) == sulong(18_446_744_073_709_551_612uL)); Was it the right idea to fix it? And if so, do I always have to use a suffix when the number is bigger than uint?

May 25 2013

Namal:And if so, do I always have to use a suffix when the number is bigger than uint?It looks a bit silly, I agree. Bye, bearophile

May 25 2013

On Saturday, 25 May 2013 at 10:15:42 UTC, bearophile wrote:Namal:Well, now I have same Error for signed long: else{ static if (op == "+"){ if(rhs._value > T.init && T.max - rhs._value < _value) return rhs.max; else if(rhs._value < T.init && T.min - rhs._value > _value) return rhs.min; } static if (op == "-"){ if(rhs._value > T.init && T.min+rhs._value > _value) return rhs.min; else if(rhs._value < T.init && T.max + rhs._value < _value) return rhs.max; } static if (op == "/"){ if(rhs._value == -1) return rhs.max; } does work for every type exept long. Like for the addition unittest{ alias slong = Saturated!long; assert(slong(9_223_372_036_854_775_806) + slong(2) == slong(9_223_372_036_854_775_807)); assert(slong(9_223_372_036_854_775_806) + slong(-3) == slong(-9_223_372_036_854_775_808)); } The first test is ok, but second wont even compile. Even if I append a L to each number.And if so, do I always have to use a suffix when the number is bigger than uint?It looks a bit silly, I agree. Bye, bearophile

May 25 2013

On 05/25/2013 04:34 AM, Namal wrote:assert(slong(9_223_372_036_854_775_806) + slong(-3) == slong(-9_223_372_036_854_775_808)); } The first test is ok, but second wont even compile. Even if I append a L to each number.According to the "Integer Literals" section here: http://dlang.org/lex.html Decimal literals are resolved as either int or long. 9_223_372_036_854_775_808 cannot fit either of those types. If you want ulong, you must either write the literal in hexadecimal or binary format or provide the UL suffix. Ali

May 25 2013

I have one more question towards using unsigned datatype assert(sint(-2_147_483_647) - sint(3) == sint(-2_147_483_648)); assert(sint(-2_147_483_647) - sint(3) == sint(2_147_483_648)); Here I get an error for the second line, because it cannot be convertet if i use unsigned assert(sint(-2_147_483_647) - sint(3) == sint(-2_147_483_648)); assert(sint(-2_147_483_647) - sint(3) == sint(2_147_483_648u)); it makes no difference and I get an error. Why doesn't the minus sign matter here and how do I fix this? Especially where I have to use u assert(slong(-9_223_372_036_854_775_807) - slong(2) == slong(-9_223_372_036_854_775_808u)); assert(slong(-9_223_372_036_854_775_807) - slong(2) == slong(9_223_372_036_854_775_808u)); Also tried this with hex numbers but it is same with them.

May 25 2013

On 05/25/2013 11:57 AM, Namal wrote:I have one more question towards using unsigned datatype assert(sint(-2_147_483_647) - sint(3) == sint(-2_147_483_648)); assert(sint(-2_147_483_647) - sint(3) == sint(2_147_483_648)); Here I get an error for the second line, because it cannot be convertetIt helps a lot if you tell the error message. After making some assumption I was able to produce an error message: Error: cannot implicitly convert expression (2147483648L) of type long to int It makes sense if sint is Saturated!int. 2147483648 is long but the struct member is int.if i use unsigned assert(sint(-2_147_483_647) - sint(3) == sint(-2_147_483_648)); assert(sint(-2_147_483_647) - sint(3) == sint(2_147_483_648u)); it makes no difference and I get an error.This time 2_147_483_648u is a uint which happens to have automatic conversion to int. Automatic type conversions can be extremely confusing. Let's see... import std.stdio; struct S { int i; } void main() { // uint converts to int: auto s = S(1u); int i; uint u = uint.max; // same: i = u; // Surprising result: assert(i == -1); } These rules are both because they are same or similar in C and also for convenience. But yes, they can be confusing... Ali

May 25 2013

Is this code available in any repo/archive somewhere? /Per

Jun 23 2013