| Thread overview | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 24, 2013 Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
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 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Namal | 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 25, 2013 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli |
> 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 25, 2013 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Namal | On Saturday, 25 May 2013 at 01:03:53 UTC, Namal wrote:
>
>> 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?
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;
}
...
--jm
| |||
May 25, 2013 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Juan Manuel Cabo | 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 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Namal | 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 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Saturday, 25 May 2013 at 10:15:42 UTC, bearophile wrote: > 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 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. | |||
May 25, 2013 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Namal | 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 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Thanks, that helped me alot. | |||
May 25, 2013 Re: Problem with object understanding and datatypes | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Namal | 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. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply