Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

Author Topic: How to force the not operator to return a byte  (Read 9269 times)

y.ivanov

• Full Member
• Posts: 132
Re: How to force the not operator to return a byte
« Reply #45 on: May 16, 2021, 12:56:40 pm »
@BobDog
I think for the original OP question it is:
Code: Pascal  [Select][+][-]
1. const
2.   a = 128;
3.   b =  64;
4.   c = not byte(a or b);

I must correct myself in my earlier post - in the latter versions of C/C++ sizeof is defined also on expressions as 'size of the static type of the expression'. Assuming our SizeOf() is working in a similar way, perhaps  the lack of a type hint makes him to return SizeOf(not 1) = SizeOf(PtrInt).

BTW, does anyone know where a decent documentation for FPC SizeOf() can be found?

@tetrastes
Thank you for your example! It shows me mostly the negative numbers two's complement representation.
I've taught a time ago, that constants are lexical substitutions, not integers. I doubt the things have changed since.

tetrastes

• Full Member
• Posts: 117
Re: How to force the not operator to return a byte
« Reply #46 on: May 16, 2021, 01:14:57 pm »
I've taught a time ago, that constants are lexical substitutions, not integers. I doubt the things have changed since.

I see you did not notice smiley at the end of that line...
To be serious, if you understand this, then I don't understand what "different interpretations" bother you?

WooBean

• Full Member
• Posts: 114
Re: How to force the not operator to return a byte
« Reply #47 on: May 16, 2021, 01:51:26 pm »
BTW, does anyone know where a decent documentation for FPC SizeOf() can be found?

See here:  https://www.freepascal.org/docs-html/rtl/system/sizeof.html

In fact sizeof(x) can accept an expression in the place of x variable or type so sizeof(1) can give 1 and sizeof(pi/2+2) can give 8 (or 10 - depending on platform).

Win7/64, Lazarus 2.0.8 win64-win64, FPC 3.0.4

tetrastes

• Full Member
• Posts: 117
Re: How to force the not operator to return a byte
« Reply #48 on: May 16, 2021, 01:58:03 pm »
I think for the original OP question it is:
Code: Pascal  [Select][+][-]
1. const
2.   a = 128;
3.   b =  64;
4.   c = not byte(a or b);

This code sets c to -193, this is not a byte (to be correct, not in range 0...255), what OP wants.
Moreover, casting (a or b) to byte is useless here: 128 or 64 = 192, byte(192) = 192.
You've taught a time ago, that constants are lexical substitutions...
« Last Edit: May 16, 2021, 02:01:36 pm by tetrastes »

tetrastes

• Full Member
• Posts: 117
Re: How to force the not operator to return a byte
« Reply #49 on: May 16, 2021, 02:24:19 pm »
Code: Pascal  [Select][+][-]
1. program test;
2.
3. {\$MODE OBJFPC}
4.
5. (*
6. https://freepascal.org/docs-html/ref/refsu4.html#x26-250003.1.1
7. ...
8.
9. Remark: The compiler decides on the type of an integer constant
10. based on the value: An integer constant gets the smallest possible
11. signed type.
12. ...
13. constants in range 128..255 are mapped to byte, etc.
14. ...
15.

These two statements contradict each other, am I wrong?

y.ivanov

• Full Member
• Posts: 132
Re: How to force the not operator to return a byte
« Reply #50 on: May 16, 2021, 02:44:06 pm »
This code sets c to -193, this is not a byte (to be correct, not in range 0...255), what OP wants.
Moreover, casting (a or b) to byte is useless here: 128 or 64 = 192, byte(192) = 192.
You've taught a time ago, that constants are lexical substitutions...

Quite not useless, since doesn't give a range check warning as with: c = byte(not (a or b));
I was taught well enough

tetrastes

• Full Member
• Posts: 117
Re: How to force the not operator to return a byte
« Reply #51 on: May 16, 2021, 02:57:17 pm »
This code sets c to -193, this is not a byte (to be correct, not in range 0...255), what OP wants.
Moreover, casting (a or b) to byte is useless here: 128 or 64 = 192, byte(192) = 192.
You've taught a time ago, that constants are lexical substitutions...

Quite not useless, since doesn't give a range check warning as with: c = byte(not (a or b));
I was taught well enough

Once more:
c = not byte(a or b) = not byte(128 or 64) = not byte(192) = not 192 = -193
is absolutely the same as
c = not (a or b) = not (128 or 64) = not 192 = -193
which also gives no warning.

BUT this is NOT what OP wants, because
c = byte(not (a or b)) = ... = 63

y.ivanov

• Full Member
• Posts: 132
Re: How to force the not operator to return a byte
« Reply #52 on: May 16, 2021, 03:34:06 pm »
Once more:
c = not byte(a or b) = not byte(128 or 64) = not byte(192) = not 192 = -193
is absolutely the same as
c = not (a or b) = not (128 or 64) = not 192 = -193
which also gives no warning.

c = byte(not(a or b)) Gives the warning. (FPC 3.2)

c = not byte(a or b) Does not.

Instead of repeating, you should try to solve it with types, not numbers.

engkin

• Hero Member
• Posts: 2818
Re: How to force the not operator to return a byte
« Reply #53 on: May 16, 2021, 03:54:25 pm »
ivanov, yes no warning, great. But now it's 4 bytes.

BobDog

• Jr. Member
• Posts: 78
Re: How to force the not operator to return a byte
« Reply #54 on: May 16, 2021, 03:57:17 pm »
@BobDog
I think for the original OP question it is:
Code: Pascal  [Select][+][-]
1. const
2.   a = 128;
3.   b =  64;
4.   c = not byte(a or b);

I must correct myself in my earlier post - in the latter versions of C/C++ sizeof is defined also on expressions as 'size of the static type of the expression'. Assuming our SizeOf() is working in a similar way, perhaps  the lack of a type hint makes him to return SizeOf(not 1) = SizeOf(PtrInt).

BTW, does anyone know where a decent documentation for FPC SizeOf() can be found?

@tetrastes
Thank you for your example! It shows me mostly the negative numbers two's complement representation.
I've taught a time ago, that constants are lexical substitutions, not integers. I doubt the things have changed since.

Code: Pascal  [Select][+][-]
1. const
2.   a = 128;
3.   b =  64;
4.   c = byte(not(a or b));
5.
6. begin
7. end.
My own snippet gives a,b as const.
c is also const (via a define).
The question was
"how to force the not operator to return a byte"
So, via a function, I have forced NOT to (eventually) return a byte via the function return.
I get no warnings with this method, although I realize that a macro is probably not really wanted.
But 63 I believe was the answer sought, so at least it produces that answer.

tetrastes

• Full Member
• Posts: 117
Re: How to force the not operator to return a byte
« Reply #55 on: May 16, 2021, 03:58:11 pm »
Once more:
c = not byte(a or b) = not byte(128 or 64) = not byte(192) = not 192 = -193
is absolutely the same as
c = not (a or b) = not (128 or 64) = not 192 = -193
which also gives no warning.

c = byte(not(a or b)) Gives the warning. (FPC 3.2)

c = not byte(a or b) Does not.

Instead of repeating, you should try to solve it with types, not numbers.

c = not (a or b)   Does not. And what?

What types are you talking about for ordinary constants? Show how " to solve it with types", I don't afraid to say that I do not know that.

And why you ignore the main:
Quote
BUT this is NOT what OP wants, because
c = byte(not (a or b)) = ... = 63

y.ivanov

• Full Member
• Posts: 132
Re: How to force the not operator to return a byte
« Reply #56 on: May 16, 2021, 04:59:32 pm »
ivanov, yes no warning, great. But now it's 4 bytes.
Oops, sorry!
Just one more typecast: c = byte( not byte(a or b) );

@BobDog
Your suggestion does the job. I've just focused on the consts, sizeof.

@tetrastes
The NOT just don't have a clue for the type of its operand and sign-extends making the value negative. Just give him what he needs, typecast, that's it.
« Last Edit: May 16, 2021, 05:05:43 pm by y.ivanov »

tetrastes

• Full Member
• Posts: 117
Re: How to force the not operator to return a byte
« Reply #57 on: May 16, 2021, 05:26:55 pm »
@tetrastes
The NOT just don't have a clue for the type of its operand and sign-extends making the value negative. Just give him what he needs, typecast, that's it.
Yes, typecast, and
Quote
Just one more typecast: c = byte( not byte(a or b) );
gives the same warning and the same binary as
c = byte( not (a or b) );

y.ivanov

• Full Member
• Posts: 132
Re: How to force the not operator to return a byte
« Reply #58 on: May 16, 2021, 05:57:44 pm »
@tetrastes
The NOT just don't have a clue for the type of its operand and sign-extends making the value negative. Just give him what he needs, typecast, that's it.
Yes, typecast, and
Quote
Just one more typecast: c = byte( not byte(a or b) );
gives the same warning and the same binary as
c = byte( not (a or b) );

I shall admit the last one was not correct either  That not operator turned out to be a tough dude.
It seems the only solution left (in the const section) is to perform some other bitwise op, like c=(\$FF xor (a or b)); or c = byte( not byte(a or b) and 255);

And perhaps I should eat up my diploma

molly

• Hero Member
• Posts: 2330
Re: How to force the not operator to return a byte
« Reply #59 on: May 16, 2021, 06:02:46 pm »
Code: [Select]
`Remark: The compiler decides on the type of an integer constantbased on the value: An integer constant gets the smallest possiblesigned type. ...constants in range 128..255 are mapped to byte, etc....`
These two statements contradict each other, am I wrong?
I fail to see how these two statements could contradict. If you still think the same after reading this post then please feel free to elaborate to make me better understand.

Quote
That means constants in the range -128..127 are mapped to shortint,
constants in range 128..255 are mapped to byte, etc.

64  = shortint
128 = byte
192 = byte

The results from the posted program confirms that the resulted answers are 1 byte in size, except when the not operator comes into play.

Take the following program that also shows the bit representation of the resulted values
Code: Pascal  [Select][+][-]
1. begin
2.   WriteLn;
3.   WriteLn(64);
4.   WriteLn(SizeOf(64));
5.   WriteLn(BinStr(64, SizeOf(64) * 8));
6.
7.   WriteLn;
8.   WriteLn(128);
9.   WriteLn(SizeOf(128));
10.   WriteLn(BinStr(128, SizeOf(128) * 8));
11.
12.   WriteLn;
13.   WriteLn(128 or 64);
14.   WriteLn(SizeOf(128 or 64));
15.   WriteLn(BinStr(128 or 64, SizeOf(128 or 64) * 8));
16.
17.   WriteLn;
18.   WriteLn(not(128 or 64));
19.   WriteLn(SizeOf(not(128 or 64)));
20.   WriteLn(BinStr(not(128 or 64), SizeOf(not(128 or 64)) * 8));
21. end.
22.

which shows:
Code: [Select]
`64101000000128110000000192111000000-19381111111111111111111111111111111111111111111111111111111100111111`
Now, I do not claim to know/understand how this is actually implemented in the compiler (haven't looked) but if I would have to take a guess then I assume (and that assumption might very well be wrong) that when the actual negation takes place that the negative flag (of the cpu) is set and that should be reflected in the result.
Because the highest bit is already set in byte value 192 (sign bit) the result is or needs to be expanded.

The same documentation that was quoted states that in that case result does not fit in the two explained ranges and that in such case it is expanded to a 64 integer.

That also seems to be confirmed by the resulted output.

fwiw: one could also opt for implementing a self written custom bye/word/dword type that is more in line with what is expected (such as how an assembler/cpu does things, and i assume OP expected the not operator to work). You could then also use your own custom operators for such a custom type and implement these operators to act/behave any which way you see fit. Even though the compiler does warn you explicitly when things are not going according to plan when using casting, but in that case simply ignoring the warnings might result in unexpected results/behaviour on the long run.

edit: typo's/rewording
« Last Edit: May 16, 2021, 07:15:03 pm by molly »