Weiss 1.4 has (GenPawn in MoveGen.c and ParseTimeControl in uci.c respectively):
const Bitboard enemies = pos->checkers ?: colorBB(!color);
Limits.depth = Limits.depth ?: 100;
=============================================
In contrast Weiss 1.3 has
const Bitboard enemies = pos->checkers ? pos->checkers : colorBB(!color);
Limits.depth = !Limits.depth ? MAX_PLY : MIN(Limits.depth, MAX_PLY);
===============================================
Visual studio complains about the code above for 1.4 indicating it expects an expression.
Could someone please comment? Thanks.
Code Question
Moderators: hgm, Rebel, chrisw
-
- Posts: 347
- Joined: Tue Nov 19, 2019 4:34 am
- Location: https://github.com/TerjeKir/weiss
- Full name: Terje Kirstihagen
Re: Code Question
The Elvis operator is cool. A ?: B is equivalent to A ? A : B, however A is only evaluated once (when that matters). If MSVC doesn't support it you can replace it with the equivalent longer form (in these cases evaluating A twice is no different from once, so the generated code should be the same).ChessRenewal wrote: ↑Tue Jul 06, 2021 4:30 pm Weiss 1.4 has (GenPawn in MoveGen.c and ParseTimeControl in uci.c respectively):
const Bitboard enemies = pos->checkers ?: colorBB(!color);
Limits.depth = Limits.depth ?: 100;
=============================================
In contrast Weiss 1.3 has
const Bitboard enemies = pos->checkers ? pos->checkers : colorBB(!color);
Limits.depth = !Limits.depth ? MAX_PLY : MIN(Limits.depth, MAX_PLY);
===============================================
Visual studio complains about the code above for 1.4 indicating it expects an expression.
Could someone please comment? Thanks.
-
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: Code Question
OMG. A shorthand for a shorthand. I thought Rust was the only language doing stuff like that (with their generics, where they now have something like... 4 ways... to write them).
And those namse: Elvis, Walrus, Spaceship. Some time ago I sw a Youtube video about someone designing his own language which had a "Rocket" operator: >>=|>
The world's gone crazy or I'm getting old.
-
- Posts: 347
- Joined: Tue Nov 19, 2019 4:34 am
- Location: https://github.com/TerjeKir/weiss
- Full name: Terje Kirstihagen
Re: Code Question
I need the rocket in C, whatever it does!mvanthoor wrote: ↑Tue Jul 06, 2021 7:57 pmOMG. A shorthand for a shorthand. I thought Rust was the only language doing stuff like that (with their generics, where they now have something like... 4 ways... to write them).
And those namse: Elvis, Walrus, Spaceship. Some time ago I sw a Youtube video about someone designing his own language which had a "Rocket" operator: >>=|>
The world's gone crazy or I'm getting old.
-
- Posts: 883
- Joined: Sat Mar 13, 2021 1:47 am
- Full name: Amanj Sherwany
Re: Code Question
Oh I hate this... C++ is rivaling Scala in introducing "simple" and powerful operators
-
- Posts: 533
- Joined: Sun Sep 06, 2020 4:40 am
- Full name: Connor McMonigle
-
- Posts: 883
- Joined: Sat Mar 13, 2021 1:47 am
- Full name: Amanj Sherwany
Re: Code Question
Oops that hurt hhh
-
- Posts: 347
- Joined: Tue Nov 19, 2019 4:34 am
- Location: https://github.com/TerjeKir/weiss
- Full name: Terje Kirstihagen
Re: Code Question
Elvis is very useful for avoiding evaluating twice.
The above obviously fails (reads twice), so you'd need to write something like:
Which is ugly compared to:
Since the operator exists I use it when possible (even if no issues evaluating twice) as I find it neat
Code: Select all
int x = readInt() ? readInt() : 0;
Code: Select all
int inputInt = readInt();
int x = inputInt ? inputInt : 0;
Code: Select all
int x = readInt() ?: 0;
-
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: Code Question
In Rust, I've shot myself in the foot several times because the compiler can optimize code and elide entire chunks all by itself. If you would write your first option, I'd not be surprised if the Rust compiler / LLVM realizes that it can cut out one evaluation by doing your second option, without you having to write it.Terje wrote: ↑Thu Jul 08, 2021 5:43 pm Elvis is very useful for avoiding evaluating twice.
The above obviously fails (reads twice), so you'd need to write something like:Code: Select all
int x = readInt() ? readInt() : 0;
Which is ugly compared to:Code: Select all
int inputInt = readInt(); int x = inputInt ? inputInt : 0;
Since the operator exists I use it when possible (even if no issues evaluating twice) as I find it neatCode: Select all
int x = readInt() ?: 0;
For example, I tried the "Replace modulo with key & (length - 1)" thing when "length" is a power of 2, but after extensive testing, it didn't improve anything. Then I discovered that you can replace modulo with "((key >> 32) * length) >> 32" for any number of TT indexes. Then I tried that, and it also didn't improve anything. I would not be surprised if either the Rust compiler or LLVM just "know" that "key % length" can be done as "((key >> 32) * nelem) >> 32", and you writing it yourself doesn't make a difference.
Rust highly prefers that you do the most logical thing. If you want to find something in a list, it prefers you to just loop over the entire list with an iterator and "break" or "return" when you find your value, instead of using a "while" loop and keeping an index and "found" condition manually.
I've found that optimizing some things like you would do in C, doesn't make a difference in Rust, or even worse, is counter-productive with regard to speed because you're effectively working against the compiler.
-
- Posts: 347
- Joined: Tue Nov 19, 2019 4:34 am
- Location: https://github.com/TerjeKir/weiss
- Full name: Terje Kirstihagen
Re: Code Question
In the readInt() example above the compiler can't 'optimize' it, as not evaluating it twice would mean something different from the code I wrote, which says to evaluate it twice (and it matters in this case).mvanthoor wrote: ↑Thu Jul 08, 2021 6:06 pmIn Rust, I've shot myself in the foot several times because the compiler can optimize code and elide entire chunks all by itself. If you would write your first option, I'd not be surprised if the Rust compiler / LLVM realizes that it can cut out one evaluation by doing your second option, without you having to write it.Terje wrote: ↑Thu Jul 08, 2021 5:43 pm Elvis is very useful for avoiding evaluating twice.
The above obviously fails (reads twice), so you'd need to write something like:Code: Select all
int x = readInt() ? readInt() : 0;
Which is ugly compared to:Code: Select all
int inputInt = readInt(); int x = inputInt ? inputInt : 0;
Since the operator exists I use it when possible (even if no issues evaluating twice) as I find it neatCode: Select all
int x = readInt() ?: 0;
In the 2 examples from Weiss the compiler will give the same compiled code for either form as I mentioned in an earlier post here, as would it if I used a full declare -> assign in if/else. I use the elvis operator because the code looks better, and the intent is clearer (Elvis does exactly what I want, while full form ternary can do other things as well).
The compiler knows to optimize modulo by power of 2 into an &. The ((key >> 32) * length) >> 32 allows using non-power-of-2 sizes, it's slower than bitmasking (and thus modulo by power of 2) tho.For example, I tried the "Replace modulo with key & (length - 1)" thing when "length" is a power of 2, but after extensive testing, it didn't improve anything. Then I discovered that you can replace modulo with "((key >> 32) * length) >> 32" for any number of TT indexes. Then I tried that, and it also didn't improve anything. I would not be surprised if either the Rust compiler or LLVM just "know" that "key % length" can be done as "((key >> 32) * nelem) >> 32", and you writing it yourself doesn't make a difference.
Many things you might think to optimize in C are similarly pointless as they are optimized by the compilers - they are incredibly good at optimizing code.Rust highly prefers that you do the most logical thing. If you want to find something in a list, it prefers you to just loop over the entire list with an iterator and "break" or "return" when you find your value, instead of using a "while" loop and keeping an index and "found" condition manually.
I've found that optimizing some things like you would do in C, doesn't make a difference in Rust, or even worse, is counter-productive with regard to speed because you're effectively working against the compiler.
If you want to find something in a list in Rust, wouldn't Iterator::find be the way?