Register | Login
Forum Index > Samples > Sample log2i
Author Message
Pages: 1
Admin
Site Admin

avatar

(send private message)

Posts: 933
Topics: 55

Location:
OverHertz Studio
[1711] Sample log2i - posted: 2015-02-15 16:30:10
Decided to write a log2 integer based function written in Zir using a lookup table.

Code:
program PE32_CUI 'Sample';

#include 'platform_def.zir';
#include 'console.zir';

byte log2i_table[32] = [
     0,  9,  1, 10, 13, 21,  2, 29,
    11, 14, 16, 18, 22, 25,  3, 30,
     8, 12, 20, 28, 15, 17, 24,  7,
    19, 27, 23,  6, 26,  5,  4, 31
];

function log2i(int32 value) {
  ecx = value;
  eax = ecx;
  
  eax >> 1; ecx |= eax; eax = ecx;
  eax >> 2; ecx |= eax; eax = ecx;
  eax >> 4; ecx |= eax; eax = ecx;
  eax >> 8; ecx |= eax; eax = ecx;
  eax >> 16; ecx |= eax;
  
  eax = 0x07C4ACDD; imul ecx; eax >> 27;
  
  eax = log2i_table[eax];
}

edi = log2i(4096);
println(edi);

wait_key();
ExitProcess(0);


Please note this is not efficient, it is to show using a table and indexing to avoid branching - see 0CodErr' BSR log2i for better method

Download Ziron
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
0CodErr
Ziron Guru
(send private message)

Posts: 199
Topics: 37

Location:
[1712] - posted: 2015-02-15 17:05:43
Maybe I do not understand some actions in your code such as:
Code:
  eax >> 1; ecx |= eax; eax = ecx;
  eax >> 2; ecx |= eax; eax = ecx;
  eax >> 4; ecx |= eax; eax = ecx;
  eax >> 8; ecx |= eax; eax = ecx;
  eax >> 16; ecx |= eax;
  
  eax = 0x07C4ACDD; imul ecx; eax >> 27;

But integer logarithm can be calculated by using 'bsr' instruction. I wrote an example for compare:
Code:
program PE32_CUI 'Sample';

#include 'platform_def.zir';
#include 'console.zir';

byte log2i_table[32] = [
     0,  9,  1, 10, 13, 21,  2, 29,
    11, 14, 16, 18, 22, 25,  3, 30,
     8, 12, 20, 28, 15, 17, 24,  7,
    19, 27, 23,  6, 26,  5,  4, 31
];

function log2i(int32 value) {
  ecx = value;
  eax = ecx;
  
  eax >> 1; ecx |= eax; eax = ecx;
  eax >> 2; ecx |= eax; eax = ecx;
  eax >> 4; ecx |= eax; eax = ecx;
  eax >> 8; ecx |= eax; eax = ecx;
  eax >> 16; ecx |= eax;
  
  eax = 0x07C4ACDD; imul ecx; eax >> 27;
  
  eax = log2i_table[eax];
}

inline function BSR_log2i($value) {eax = $value; bsr eax, eax; $return eax;}

println(NEW_LINE, 'log2i:', NEW_LINE);
edi = log2i(0x00000001); println(edi);
edi = log2i(0x00000002); println(edi);
edi = log2i(0x00000004); println(edi);
edi = log2i(0x00000008); println(edi);
edi = log2i(0x00000010); println(edi);
edi = log2i(0x00000020); println(edi);
edi = log2i(0x00000040); println(edi);
edi = log2i(0x00000080); println(edi);
edi = log2i(0x00000100); println(edi);
edi = log2i(0x00000200); println(edi);
edi = log2i(0x00000400); println(edi);
edi = log2i(0x00000800); println(edi);
edi = log2i(0x00001000); println(edi);
edi = log2i(0x00002000); println(edi);
edi = log2i(0x00004000); println(edi);
edi = log2i(0x00008000); println(edi);
edi = log2i(0x00010000); println(edi);
edi = log2i(0x00020000); println(edi);
edi = log2i(0x00040000); println(edi);
edi = log2i(0x00080000); println(edi);
edi = log2i(0x00100000); println(edi);
edi = log2i(0x00200000); println(edi);
edi = log2i(0x00400000); println(edi);
edi = log2i(0x00800000); println(edi);
edi = log2i(0x01000000); println(edi);
edi = log2i(0x02000000); println(edi);
edi = log2i(0x04000000); println(edi);
edi = log2i(0x08000000); println(edi);
edi = log2i(0x10000000); println(edi);
edi = log2i(0x20000000); println(edi);
edi = log2i(0x40000000); println(edi);
edi = log2i(0x80000000); println(edi);

println(NEW_LINE, 'BSR_log2i:', NEW_LINE);
edi = BSR_log2i(0x00000001); println(edi);
edi = BSR_log2i(0x00000002); println(edi);
edi = BSR_log2i(0x00000004); println(edi);
edi = BSR_log2i(0x00000008); println(edi);
edi = BSR_log2i(0x00000010); println(edi);
edi = BSR_log2i(0x00000020); println(edi);
edi = BSR_log2i(0x00000040); println(edi);
edi = BSR_log2i(0x00000080); println(edi);
edi = BSR_log2i(0x00000100); println(edi);
edi = BSR_log2i(0x00000200); println(edi);
edi = BSR_log2i(0x00000400); println(edi);
edi = BSR_log2i(0x00000800); println(edi);
edi = BSR_log2i(0x00001000); println(edi);
edi = BSR_log2i(0x00002000); println(edi);
edi = BSR_log2i(0x00004000); println(edi);
edi = BSR_log2i(0x00008000); println(edi);
edi = BSR_log2i(0x00010000); println(edi);
edi = BSR_log2i(0x00020000); println(edi);
edi = BSR_log2i(0x00040000); println(edi);
edi = BSR_log2i(0x00080000); println(edi);
edi = BSR_log2i(0x00100000); println(edi);
edi = BSR_log2i(0x00200000); println(edi);
edi = BSR_log2i(0x00400000); println(edi);
edi = BSR_log2i(0x00800000); println(edi);
edi = BSR_log2i(0x01000000); println(edi);
edi = BSR_log2i(0x02000000); println(edi);
edi = BSR_log2i(0x04000000); println(edi);
edi = BSR_log2i(0x08000000); println(edi);
edi = BSR_log2i(0x10000000); println(edi);
edi = BSR_log2i(0x20000000); println(edi);
edi = BSR_log2i(0x40000000); println(edi);
edi = BSR_log2i(0x80000000); println(edi);

wait_key();
ExitProcess(0);
Admin
Site Admin

avatar

(send private message)

Posts: 933
Topics: 55

Location:
OverHertz Studio
[1713] - posted: 2015-02-15 17:27:32
The idea of my sample is more of using table as sample, but using BSR, i never thought about that, it is sure to be 1000% faster of course, thanks smile

Download Ziron
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
0CodErr
Ziron Guru
(send private message)

Posts: 199
Topics: 37

Location:
[1726] - posted: 2015-02-18 13:19:12
The idea of my sample is more of using table as sample

For this purpose i suggest example which translate file size in bytes to human readable format, it also uses $log2i:
Code:
program PE32_CUI 'readable_f_size';

#include 'platform_def.zir';
#include 'console.zir';
#include 'zirutils.zir';
#include 'strutils.zir';

byte  units[] = [
      0x62, 0x00, 0x00, 0x00, // byte     // b
      0x6B, 0x62, 0x00, 0x00, // kilobyte // kb
      0x4D, 0x62, 0x00, 0x00, // Megabyte // Mb
      0x47, 0x62, 0x00, 0x00  // Gigabyte // Gb
];

function ReadableFileSize(dword bytes; char* buffer) {
uses ebx;
  eax = bytes; ecx = 0;
  while (eax => 1024) {eax += 512; ecx++; eax >> $log2i(1024);}
  ebx = @[ecx*4 + @units];
  dw2str(eax, buffer);
  strAppend(buffer, ebx, -1);
  return buffer;
}

char buf[32];

inline procedure Test($bytes) {
  eax = ReadableFileSize($bytes, @buf); println([char*]eax);
}

test(0);
test(500);
test(1000);
test(1023);
test(1024);
test(1025);
test(2000);
test(2000000);
test(1000000000);
test(1073741824);
test(2051234567);

wait_key();
ExitProcess(0);

Of course it can has more readable code when you fix some bugs smile
0CodErr
Ziron Guru
(send private message)

Posts: 199
Topics: 37

Location:
[1727] - posted: 2015-02-18 13:24:24
Also someone can want to get 64-bit file size in 32 bit mode.
Code:
program PE32_CUI 'readable_f_size';

#include 'platform_def.zir';
#include 'console.zir';
#include 'zirutils.zir';
#include 'strutils.zir';

byte  units[] = [
      0x62, 0x00, 0x00, 0x00, // byte      // b
      0x6B, 0x62, 0x00, 0x00, // kilobyte  // kb
      0x4D, 0x62, 0x00, 0x00, // Megabyte  // Mb
      0x47, 0x62, 0x00, 0x00, // Gigabyte  // Gb
      0x54, 0x62, 0x00, 0x00, // Terabyte  // Tb
      0x50, 0x62, 0x00, 0x00, // Petabyte  // Pb
      0x45, 0x62, 0x00, 0x00  // Exabyte   // Eb      
];

// this function returns valid values for 
// sizes from 0 to 0xFFFFFFFFFFFFFDFF bytes (16 Exabytes - 512 bytes)
//
// eax += 512; adc edx, 0; << need to avoid 
// rounding errors i.e. if 1700 bytes then 
// return 2 kb(1.66 round to 2)
function ReadableFileSize64(dword bytesLo, bytesHi; char* buffer) {
uses ebx;
  eax = bytesLo; edx = bytesHi; ecx = 0;
  while ((eax => 1024) OR (edx <> 0)) {
    eax += 512; adc edx, 0;     
    shrd eax, edx, $log2i(1024);
    shr edx, $log2i(1024);
    ecx++;
  }
  ebx = @[ecx*4 + @units];
  dw2str(eax, buffer);
  strAppend(buffer, ebx, -1);
  return buffer;
}

char buf[32];

inline procedure Test($bytesHi, $bytesLo) {
  eax = ReadableFileSize64($bytesLo, $bytesHi, @buf); 
  println([char*]eax);
}

// (hi_dword, lo_dword) // low and hi parts of qword filesize
test(0,          0);
test(0,          500);
test(0,          1000);
test(0,          1023);
test(0,          1024);
test(0,          1025);
test(0,          2000);
test(0,          2000000);
test(0,          1000000000);
test(0,          1073741824);
test(0,          2051234567);
test(0x1,        0xC0000000);
test(0x30FF,     0xFFFFFFE8);
test(0xD0000000, 0x00000000);
test(0xFFFFFFFF, 0xFFFFFDFF);

wait_key();
ExitProcess(0);

It also can be more readable when you fix some bugs(also bug with qword) smile
Admin
Site Admin

avatar

(send private message)

Posts: 933
Topics: 55

Location:
OverHertz Studio
[1728] - posted: 2015-02-18 14:01:36
Nice idea, maybe I can add your functions to the new RTL units (hopefully ready in a couple more releases time)

Hopefully today I will get around to fixing all reported issues smile

Download Ziron
Get free hosting for Ziron related fan-sites and Ziron projects, contact me in private message.
Pages: 1
create new reply


Quick reply:

Message:



Currently Active Users:
There are currently 2 user(s) online. 0 member(s) and 2 guest(s)
Most users ever online was 1046, January 28, 2022, 2:08 pm.


Statistics:
Threads: 225 | Posts: 1848 | Members: 51 | Active Members: 51
Welcome to our newest member, yecate
const Copyright = '2011-2024 © OverHertz Ltd. All rights reserved.';
Web development by OverHertz Ltd