User Tools

Site Tools


en:pfw:2log

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
en:pfw:2log [2023-09-04 18:09] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1en:pfw:2log [2023-09-04 18:09] (current) – ↷ Seite von pfw:2log nach en:pfw:2log verschoben uho
Line 1: Line 1:
 +{{pfw:banner.png}}
 +==== 2LOG, calculate binary logarithm ====
 +
 +The 2LOG routine was the result of the need for converting a linear input into something with a more logarithmic character. There was no need for high accuracy, but rather a short reliable routine. The routine uses a very simple principle, but the result is surprisingly useable. A prime example where focussing on the essentials results in an excellent solution.
 +
 +The 2LOG routine produces as output a fixed floating point number with 8 bits after the decimal point. ( x...x**.**xxxxxxxx ) The number of bits before the decimal point depends on the native width of the stack.
 +
 +=== The principle used is this: ===
 +
 +looking at the number to be converted in binary representation: (see grafic below) - step 1: take the bit-position+1 of the first set bit as number before the decimal point - step 2: as 8 bit fraction take the highest 8 bits following the most most significant set bit. If there are less than 8 bits, pad the end with cleared bits up to 8 bits.
 +
 +It is good to notice that the fractional part forms a linear interpolation between two consecutive log numbers. For most purposes that is accurate enough.
 +
 +<html><img src="https://user-images.githubusercontent.com/4964288/167205050-76579ac1-2707-4037-9d6d-2a5452b601b5.png" alt="drawing" width="500" height="250"/></html>
 +
 +=== the generic Forth program ===
 +
 +As example we look at the routine for a 16b Forth. The other example is suitable for all Forth implementations.
 +
 +<code forth>
 +
 +decimal
 +: 2LOG16b ( u -- y )
 +    16 0 do
 +        s>d if
 +            2* 8 rshift                 \ linear interpolation
 +            15 i -                      \ logarithmic class
 +            8 lshift or leave
 +        then 2*
 +    loop ;
 +</code>
 +
 +  * The programs does maximal 16 loops.
 +  * For each loop S>D is used to check if the most significant bit is set. If not, then the program shifts the number 1 bit to the left with 2*.
 +  * Otherwise it calculates the output.
 +    * The logarithmic part is calculated by subtracting the index from 15.
 +    * The fractional part is calculated by shifting to left with 1bit, followed by shifting 8 bits to the right.
 +  * Finally, both numbers are then combined into one number with a shift and or as final output.
 +
 +=== The general version ===
 +
 +The general version is suitable for all Forth-implementations which have a multiple of 8 bits as cell-width. It functions in exactly the same way as the 16b example above. But during compilation it calculates the, for that Forth-implementation relevant, values for the do**...**loop, shift and subtraction.
 +
 +<code forth>
 +: 2LOG ( u -- y )
 +    [ 8 cells ] literal 0 do                \ #bits/cell
 +        s>d if  2*
 +            [ 8 cells 8 - ] literal rshift  \ linear interpolation
 +            [ 8 cells 1- ]  literal  i -    \ logarithmic class
 +            8 lshift or leave
 +        then 2*
 +    loop ;
 +</code>
 +
 +==== Contributions ====
 +
 +<html><h2 style="background-color:yellow">Alternative Implementations</h2></html>
 +