r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[rebcode] Rebcode discussion

Gabriele
14-Oct-2005
[252]
log base b (x) = log (x) / log (b)
BrianH
14-Oct-2005
[253]
I still think the native version would be more efficient than that. 
Base-2 logs help a lot with binary to decimal conversion (or was 
it vice-versa?). I may be wrong here though...
Pekr
14-Oct-2005
[254]
one opcode more or less should not be the difference,no? So why not 
to add it if found usefull? :-)
BrianH
14-Oct-2005
[255x3]
Wasn't there a log2 instruction in x86 before the floating-point 
processor was incorporated onto the main chip?
Floating point division on x86 is quite slow in comparison to integer 
operations, sometimes more than 10 times as slow.
(depending on the cpu)
Pekr
14-Oct-2005
[258]
and log2 does help with it? Just asking - most of the time I dunno 
what you are talking about here :-)
Ladislav
14-Oct-2005
[259]
you don't have to use division: (log-2 x) = (log-e x) * (log-2 e)
BrianH
14-Oct-2005
[260x2]
They used division in their above solution.
Adding a mul instead of a div isn't such a big deal, in comparison.
Ladislav
14-Oct-2005
[262]
I think, that everyone knows, that division by a constant can be 
replaced multiplication by its reciprocal, which is a constant too 
:-)
BrianH
14-Oct-2005
[263]
So your example would be (log-2 x) = (log-e x) * (1 / (log-e 2))

especially since e isn't defined as a constant in REBOL, and log-2 
isn't a rebcode opcode so we can't use it here.
Ladislav
14-Oct-2005
[264x2]
of course you can, just define: log-2e: log-2 e
log-2e: log-2 exp 1
BrianH
14-Oct-2005
[266]
Ah, exp 1. It has been a while, I had forgotten.
Ladislav
14-Oct-2005
[267]
actually, it may be of a value to have: e: exp 1
BrianH
14-Oct-2005
[268x3]
I suppose those "constants" could be calculated ahead of time and 
just inserted in the code as local variables. Well, that solves the 
functionality and memory (mine) problems. Still, it seems like C 
libraries and such must have a better way of doing this - it seems 
a bit inefficient.
On a binary machine, wouldn't log-e and log-10 be implemented on 
a lower level on top of log-2, instead of the other way around?
I'm probably just misunderstanding logarithms.
Gabriele
14-Oct-2005
[271]
i don't think there's any way to implement log-2 any faster then 
log-e
Ladislav
14-Oct-2005
[272x2]
On a binary machine, wouldn't log-e and log-10 be implemented on 
a lower level on top of log-2, instead of the other way around?
 not exactly, it is a kind of a "mix" AFAICT
see http://en.wikipedia.org/wiki/Natural_logarithm
eFishAnt
14-Oct-2005
[274]
log-2 (and 8, 16, etc) should just be bit shifting and "bit-tabling" 
since 2 is a "natural number" in computers....no "Math" needed...;-)
Ladislav
14-Oct-2005
[275x3]
only if you want just integer part of the result, though
otherwise you really need some multiplication
(which is a bit shifting etc. too ;-)
Pekr
14-Oct-2005
[278]
Do you think anything like following would be possible? (simply trying 
to get some real-life example usability of rebcode, e.g rewriting 
some mezzanines). Some time ago, we've got 'remove-each. But initially 
there was not any such function available ... so I wanted to filter 
directory listing - it was rather slow in rebol, untill remove-each 
appeared. I would like to teas rebol level vs native vs rebcode. 
Could such functionality be achieved in rebcode? I mean - take a 
block, traverse it, remove each element where last char is #"/"?
Gabriele
14-Oct-2005
[279x2]
Steve: but you need a loop! so, unless you have that in hardware 
(and it still doesn't seem doable to me for floating point), log-e 
will be easier to compute (see wikipedia article)
petr: PARSE is probably going to be much faster than rebcode for 
something like that, IMHO. after all, PARSE is a specialized virtual 
machine.
Ladislav
14-Oct-2005
[281x2]
the REMOVE-EACH success is based on a better algorithm. It is possible 
to implement a pure REBOL mezzanine doing much better than a "dummy 
approach does"
...as well as you may be able to implement a C algorithm doing worse 
than a proper REBOL approach can do
Pekr
14-Oct-2005
[283x2]
Gabriele - thanks for the idea with parse and the note about it being 
a VM of some kind .... now I get it a little bit better :-)
we currently have insert, copy, do you think 'find would make sense? 
It is like moving in loop till some char :-) well, could be done 
in rebcode itself or so it seems :-)
Gabriele
14-Oct-2005
[285x2]
apply result find [series value]   :-)
Brian: it's confirmed, BRAW takes a relative offset like BRA.
BrianH
14-Oct-2005
[287x4]
Ladislav, looking back on the code I've written in REBOL using logarithms, 
it turns out that the integer part of log-2 was all I was interested 
in. Apparently I have just been using it to find out how many bits 
are needed to hold a particular integer value when I've needed such 
info. I haven't used logarithms for regular computation since I was 
in grade school. Oh well, I guess I'm not the target market for the 
log-* functions. Thanks for the link, it's been interesting reading!
Gabriele, a relative offset. Darn. That is going to make BRAW a lot 
more difficult to use for me. What kind of programming tasks are 
made easier with a relative computed goto?
See, even BRA is converted from an absolute offset to a relative 
offset at assembly time. Having BRAW be relative would mean making 
that conversion at runtime every time you want to make the jump, 
and then rewriting that computation every time you make a minor adjustment 
to your code, recounting instructions by hand and subtracting the 
new constant.
I suppose a new opcode BRAWA could be added as a rewrite rule to 
a calculation and a BRAW, but that kind of rewrite rule adds a temporary 
variable and so isn't recursion-safe or safe for use by multiple 
rebcode functions without some tricks.
Volker
14-Oct-2005
[291x2]
HAve not looked close in rebcode. But maybe switch-statements? There 
you know where the branch is, and can calculate the right table. 
another switch could be implemented by reserving enough space for 
each branch, say 8 opcodes. and then simply shift the switch-argument 
by 3 (= *8) and braw.
Also makes it easierto port redcode to rebcode *g*
BrianH
14-Oct-2005
[293x5]
Watch out, I have been giving this some thought and have a big message 
coming :)
(Thinking out loud) It occurs to me that computed branches would 
be a lot easier if you could reference the target values in your 
code, so that you have something to compute with. If the offsets 
were absolute you could just assign them to the label words (something 
that could be done in the first pass of the assembler rewrite of 
the branch statements). Relative offsets could be calculated pretty 
easily if you had something like a HERE opcode that would assign 
the current position to a variable that could be used soon afterwards 
to calculate the relative offset. For that matter, the HERE opcode 
could perform the assignment of the original label as well, and even 
be accomplished by a rewrite rule in the branch fixup pass of the 
assembler.


Here's my proposal for a HERE assembler directive. No native opcodes 
would need to be added - this would be another directive like label. 
This directive could be used to set the target values to words for 
later computation. Assuming BRAW stays relative and no absolute computed 
branch is added, it could also be used in computations to convert 
from absolute to relative offsets. This would be sufficient to make 
computed branches practical.


- A new directive HERE, taking two arguments, a word and a literal 
integer.

It would set the word to the position of the HERE directive, plus 
an offset specified in the second parameter. The offset would need 
to be a literal because the calculation would be performed ahead 
of time by the assembler - 0 would mean no offset. If you don't want 
to reset the position every time you branch to the word use an offset 
of 3. Resetting the word after every branch would allow its use as 
a temporary in absolute-to-relative calculations, but that would 
only be an advantage until the JIT or optimizer is implemented - 
the choice would be up to the developer. Having a mandatory second 
argument is necessary for reasons that will become clear later.


- The HERE directive would be rewritten away in the fix-bl function 
of the assembler like this:

REBOL []  ; So I could use SciTE to write this message

fix-bl: func [block /local labels here label] [
    labels: make block! 16
    block-action: :fix-bl
    if debug? [print "=== Fixing binding and labels... ==="]
    parse block [
        some [
            here:
            subblock-rule (here/1: bind here/1 words)
            |

            'label word! (here/1: bind here/1 words insert insert tail labels 
            here/2 index? here)
            |  ; Beginning of the added code
            'here word! integer! (

                here/1: bind 'set words  ; This is why HERE needs two arguments

                here/3: here/3 + index? here  ; Offset from position of this directive
                if (here/3 < 1) or (here/3 > 1 + length? block) [
                    error/with here "Offset out of bounds:"
                ]
            )  ; End of the added code
            |
            opcode-rule (here/1: bind here/1 words)
            |
            skip (error here)
        ]
    ]
    parse block [
        some [
            here:
            ['bra word! | 'brat word! | 'braf word!] (

                if not label: select labels here/2 [error/with here "Missing label:"]
                here/2: label - index? here
            )
            |
            opcode-rule
            |
            skip (error here)
        ]
    ]
]
Note that the HERE directive would need to be implemented after the 
user-defined rewrite rules have been run because those can change 
the lengths of the offsets. This is the same reason the literal branches 
are calculated at this point.
In case you missed it in the code, the trick is to have the assembler 
calculate the offset and then convert the HERE directive to a SET.
Once you have something like this directive, a branch can be done 
with the addition of just two operations, a SET and a SUB, to the 
relative BRAW. The SET would be a converted HERE.
Gabriele
14-Oct-2005
[298x3]
about HERE... can't you just do that with:
(hmm, no can't, sorry.)
seems to make sense. i'll see what Carl thinks about it.
BrianH
14-Oct-2005
[301]
Feel free to rename it, but "here" made sense to me.