[squeak-dev] The Inbox: Kernel-fn.1151.mcz

Eliot Miranda eliot.miranda at gmail.com
Thu Mar 22 02:20:57 UTC 2018


On Wed, Mar 21, 2018 at 5:15 PM, Levente Uzonyi <leves at caesar.elte.hu>
wrote:

> On Wed, 21 Mar 2018, Eliot Miranda wrote:
>
>
>>
>> On Wed, Mar 21, 2018 at 2:48 PM, Levente Uzonyi <leves at caesar.elte.hu>
>> wrote:
>>       On Tue, 20 Mar 2018, Chris Cunningham wrote:
>>
>>             Hi.  Reopening this thread - probably tomorrow will implement
>> 'better' solution (with documentation).
>>
>>             On Sat, Feb 10, 2018 at 12:03 PM, Tobias Pape <
>> Das.Linux at gmx.de> wrote:
>>
>>                   > On 10.02.2018, at 20:36, Tony Garnock-Jones <
>> tonyg at leastfixedpoint.com> wrote:
>>                   >
>>                   > On 02/10/2018 07:02 PM, Levente Uzonyi wrote:
>>                   >> So,
>>                   >>    a perform: {#or:. #xor:. #and:} atRandom with: b
>>                   >> would just work for that imaginary interpreter if b
>> were a Boolean.
>>                   >
>>                   > Yes, that "interpreter" works just fine today, if b
>> is a Boolean. It's
>>                   > the case where b is a Boolean-producing expression -
>> such as in a "lazy"
>>                   > interpreter - that doesn't work without Fabio's
>> proposed change.
>>                   >
>>                   > I went and looked at the ANSI standard (draft), btw
>> [1].
>>                   >
>>                   > There, #xor: is specified as taking only a boolean.
>>                   >
>>                   > So this would be an extension, potentially affecting
>> portability, for
>>                   > what that's worth these days.
>>                   >
>>                   > I think the performance objection has been
>> well-refuted, and I see the
>>                   > consistency benefit as being real, but probably
>> pretty limited, and I
>>                   > kind of don't like the potential portability
>> implications.
>>
>>                   I presume the main "feeling" here is parallelity:
>>
>>                   #& takes an evaluated boolean   #and: takes an
>> unevaluated block
>>                   #| takes an evaluated boolean   #or: takes an
>> unevaluated block
>>
>>                   #xor: takes an evaluated boolean but looks like #and:
>> and #or:,
>>                   So it seems to belong to the right side, and then we
>> think again about
>>                   the left side, come up with symbols, only to find that
>> #~= and #~~ are already there.
>>
>>                   So, just lets go all the way and document #xor: better,
>> not making take it a block,
>>                   maybe pointing out that #~= ist typically better fitted…
>>
>>                   Best regards
>>                           -Tobias
>>
>>
>>             So, I have written some tests for speed and 'ensuring the
>> arguments are booleans', with another proposed solution.
>>
>>             First, speed:
>>
>>             #xor: base
>>             #~= is 124% slower (or 2-1/4 as much time as existing xor:
>> method)
>>             #~~ is 75% faster
>>             #cbcXor: is 32% slower
>>
>>             Note: for real speed, use ~~ , not ~= !
>>
>>             Why cbcXor: ?  It is the only one that makes sure the
>> arguments are boolean - fails otherwise.
>>
>>
>> Here is a simpler and faster alternative:
>>
>> True >> #xor: aBoolean
>>
>>         aBoolean ifTrue: [ ^false ] ifFalse: [ ^true ]
>>
>> False >> #xor: aBoolean
>>
>>         aBoolean ifTrue: [ ^true ] ifFalse: [ ^false ]
>>
>>
>> and is this noticeably slower?
>>
>>  True >> #xor: aBoolean
>>
>>         ^aBoolean ifTrue: [ false ] ifFalse: [ true ]
>>
>> False >> #xor: aBoolean
>>
>>         ^aBoolean ifTrue: [ true ] ifFalse: [ false ]
>>
>
> Yes, it is. Here are the bytecodes for your suggestion:
>
> 33 <10> pushTemp: 0
> 34 <99> jumpFalse: 37
> 35 <71> pushConstant: true
> 36 <90> jumpTo: 38
> 37 <72> pushConstant: false
> 38 <7C> returnTop
>
> And for my variant:
>
> 33 <10> pushTemp: 0
> 34 <98> jumpFalse: 36
> 35 <79> return: true
> 36 <7A> return: false
>
> I measured the latter to be 14% faster.


For xor: it's hardly worth it.  Nicer if the compiler and decompiler did
the transformation...


>
>
> Levente
>
>
>
>> but I would much prefer to see either
>>
>> Boolean>>xor: aBooleanOrBlock
>>
>>     ^ aBooleanOrBlock value not
>>
>> or
>>
>> True >> #xor: aBooleanOrBlock
>>
>>         ^aBooleanOrBlock value ifTrue: [ false ] ifFalse: [ true ]
>>
>> False >> #xor: aBooleanOrBlock
>>
>>         ^aBooleanOrBlock value ifTrue: [ true ] ifFalse: [ false ]
>>
>> The lack of symmetry with and: and or: is, IMO, bad.
>>
>>
>>       Levente
>>
>>
>>             Tests to run:
>>
>>             First, install
>>
>>             True>>cbcXor: boolean
>>             ^boolean isFalse
>>             True>>isTrue
>>             ^true
>>             True>>isFalse
>>             ^false
>>             False>>cbcXor: boolean
>>             ^boolean isTrue
>>             False>>isFalse
>>             ^true
>>             False>>isTrue
>>             ^false
>>
>>             "Setup"
>>             pairs := #( true false true true false false false true ).
>>             invalidPairs := { true. 1. true. #[ 1 3 0 9 ]. true. 'abc'.
>> false. 1. false. #[ 1 3 0 9 ]. false. 'abc'. 'abc'. true. #[ 1 3 0 9 ].
>> false. }.
>>             methods := {
>>             [:f :s| ].
>>             [:f :s| f xor: s].
>>             [:f :s| f cbcXor: s].
>>             [:f :s| f ~= s].
>>             [:f :s| f ~~ s].
>>             }.
>>             "Validity Test"
>>             validCheck := methods collect: [:m|
>>             {
>>             m sourceString.
>>             #( true false false true ) = (pairs pairsCollect: [:a :b| [m
>> value: a value: b] on: Error do: [#error]])
>>             ifTrue: ['Valid'] ifFalse: ['ERRORS'].
>>             pairs pairsCollect: [:a :b| [m value: a value: b] on: Error
>> do: [#error]].
>>             }].
>>             "all methods are valid"
>>             "Testing that non-booleans actually result in errors, and not
>> false positive/negatives"
>>             invalidCheck := methods collect: [:m|
>>             {
>>             m sourceString.
>>             ((invalidPairs pairsCollect: [:a :b| [m value: a value: b]
>> on: Error do: [#error]]) select: [:r| r = #error]) size = 8
>>             ifTrue: ['Valid'] ifFalse: ['ERRORS'].
>>             invalidPairs pairsCollect: [:a :b| [m value: a value: b] on:
>> Error do: [#error]].
>>             }].
>>             "Only #cbcXor: correctly fails all of these.  Some
>> interesting results..."
>>             "Timing test.  Need to run 10,000,000 to get reasonable
>> distinctions on my machine."
>>             timing := methods collect: [:m|
>>             { m sourceString.  [[10000000 timesRepeat: [pairs pairsDo:
>> m]] timeToRun] on: Error do: [#invalid]. }
>>             ].
>>             "And showing percentage slower"
>>             base := timing first second.
>>             bench := timing second second - base.
>>             timing allButFirst collect: [:res| { res first. this := res
>> second - base. ((this - bench) * 100 / bench) rounded. }].
>>
>>             Thanks,
>>             cbc
>>
>>
>>
>>
>>
>>
>>
>> --
>> _,,,^..^,,,_
>> best, Eliot
>>
>>
>
>
>


-- 
_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20180321/8ed26daa/attachment-0001.html>


More information about the Squeak-dev mailing list