Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using macros to define exponent, logarthim, etc. 1

Status
Not open for further replies.

nexius

Programmer
Jul 8, 2000
109
CA

Is it possible to use macros to define the logarithm function, for integers?

I'm constructing an array whose size depends on some variables defined as #defines. (It's actually the log of a few of these variables)

At the moment I'm calling a static method to allocate the array dynamically, even though its size can easily be calculated from the constants...

I could of course just calculate it myself, but I'd really like to keep it variable, so I can increase/detail what is basically the detail of my program...

Any help?
I have no idea where to go from here.

Thanks for your time!
 
log2(NN) actually is number of position of highest significant bit of NN. So

#if NN & 0x40000000
#define LOG_2_NN 30
#elif NN & 0x20000000
#define LOG_2_NN 29
#elif NN & 0x10000000
#define LOG_2_NN 28
#elif
<...>
#elif NN & 0x00000001
#define LOG_2_NN 0
#else
#define LOG_2_NN (-MAXINT)
#endif
:)
 
> At the moment I'm calling a static method to allocate the array dynamically
What are the disadvantages of this?
It's just one line of code which happens just once in the code, and is rather easy to explain.

The alternative seems to me to be something like what mingis has written, or some big macro for whatever log polynomial seems appropriate.
[tt]#define LOG(x) (x)-(x*x)/2+(x*x*x)/3[/tt]


--
 
[LOL] Macros logic.
Don't use macrosses :). C++ is a language gives enough possibilities to work without macrosses. No program logic could be done in macrosses.

Ion Filipski
1c.bmp
 
Why not? Salem's comment looks quite attractive :) (except of polynomial itself - it seems to be not for log)
 
The trend of all novices are to invent something unusual. It includes using of macros in place where they are not needed. Is the same thing like using goto instead of if/while/... . The possibility of using macros exist in C++ not for making macros based programs.

Ion Filipski
1c.bmp
 
I have to agree with Ion on this, any macro solution is going to look horrible compared to alternatives.


--
 
>Why not? Salem's comment looks quite attractive :)

attractive is obviously in the eye of the beholder.

When talking about attractive code, to me that means properties such as type-safe and predictable.

I dare you to do a
Code:
LOG(i++)
for some int i and predict the result.



/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
> Is the same thing like using goto instead of if/while/...

Actually, using unorthodox methods of coding such as goto statements can be good _IF_ you know what you're doing. I had this professor in college who was this tremendously smart guy; he worked at Princteton U part time and wrote several Fortran textbooks. I took his class on compilers and was suprised to see the lexical analyzer function just littered with goto statements. It was well structured, though, and easy to follow and modify, so in this particular situation, using goto worked. I can post a section of the code if anyone's interested.
 
Well for every rule there it least one exception.
>I can post a section of the code
Yes please.

/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
Here the routine that does tokenization:

(pardon my Pascal)

Code:
(* globals *)
const
  rounderror=1/1000000;
  debug=false;
type
  tokenstrtype=string[30];
  vartype=(realnum,proc);
  tokentype=string[10];
  tokenptr=^tokenlist;
  tokenlist=record
              token:tokentype;
              ref:integer;
              next:tokenptr;
            end;
  vartablenode=record
                 lexref:integer;
                 case kind:vartype of
                   realnum : (value:real);
                   proc    : (address:tokenptr);
               end;
  pstacknode=^stacknode;
  stacknode=record
              value:real;
              next:pstacknode;
            end;
  vartable=array[1..50] of vartablenode;
  ptable=^vartable;
const
  dumpfilename='dump.txt';
  literaltablesize=35;
  literaltable:array [1..literaltablesize] of tokenstrtype=(
    'program','print','end',':=','+',
    '-','*','/','^','read',
    '(',')','if','then','else',
    'and','or','not','=','>',
    '<','>=','<=','<>','for',
    'to','step','do','procedure','call',
    ',','global','local',':','real');
var
  globaltable,localtable:ptable;
  consttable,lexvartable:array[1..100] of tokenstrtype;
  progfile,dumpfile:text;
  list,curptr:tokenptr;
  ch:char;
  lextablesize,consttablesize,globalsize,localsize,lines,reclevel:integer;
  callstack:pstacknode;
  p:pointer;

(* snip *)

procedure gettokens;
label start,literal,halfassign,greater,less,
      varname,wholenum,point,fracnum,endline,exit;
var tokenstr:tokenstrtype;
    ref:integer;
    dummy:boolean;
  begin
  tokenstr:='';
  getnextchar;
  start:
    case ch of
      'a'..'z'            : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto varname;
                            end;
      '0'..'9'            : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto wholenum;
                            end;
      '+','-','*','/','^',
      '(',')','=',','     : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto literal;
                            end;
      ':'                 : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto halfassign;
                            end;
      '>'                 : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto greater;
                            end;
      '<'                 : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto less;
                            end;
      #13,#26             : begin
                            tokenstr:=tokenstr+ch;
                            getnextchar;
                            goto endline;
                            end;
      ' ',#9,#10          : begin
                            getnextchar;
                            goto start;
                            end;
      else begin
           errormessage('Syntax error');
           end;
    end;  (*case*)
  halfassign:
    case ch of
      '=' : begin
            tokenstr:=tokenstr+ch;
            getnextchar;
            goto literal;
            end;
      else begin
           dummy:=inlittable(tokenstr,ref);
           inserttoken('literal',ref);
           tokenstr:='';
           goto start;
           end;
    end;  (*case*)
  greater:
    case ch of
      '=','>' : begin
                tokenstr:=tokenstr+ch;
                getnextchar;
                goto literal;
                end;
      else begin
           dummy:=inlittable(tokenstr,ref);
           inserttoken('literal',ref);
           tokenstr:='';
           goto start;
           end;
    end;  (*case*)
  less:
    case ch of
      '=' : begin
            tokenstr:=tokenstr+ch;
            getnextchar;
            goto literal;
            end;
      else begin
           dummy:=inlittable(tokenstr,ref);
           inserttoken('literal',ref);
           tokenstr:='';
           goto start;
           end;
    end;  (*case*)
  varname:
    case ch of
      'a'..'z','0'..'9','_' : begin
                              tokenstr:=tokenstr+ch;
                              getnextchar;
                              goto varname;
                              end;
      else begin
           if inlittable(tokenstr,ref) then
             begin
             inserttoken('literal',ref)
             end
           else
             begin
             if not inlexvartable(tokenstr,ref) then
               begin
               insertlexvartable(tokenstr);
               end;
             inserttoken('varname',ref);
             end;
           tokenstr:='';
           goto start;
           end;
    end;  (*case*)
  wholenum:
    case ch of
      '0'..'9' : begin
                 tokenstr:=tokenstr+ch;
                 getnextchar;
                 goto wholenum;
                 end;
      '.'      : begin
                 tokenstr:=tokenstr+ch;
                 getnextchar;
                 goto point;
                 end;
      else begin
           if not inconsttable(tokenstr,ref) then
             begin
             insertconsttable(tokenstr);
             end;
           inserttoken('constant',ref);
           tokenstr:='';
           goto start;
           end;
    end;  (*case*)
  point:
    case ch of
      '0'..'9' : begin
                 tokenstr:=tokenstr+ch;
                 getnextchar;
                 goto fracnum;
                 end;
      else begin
           errormessage('Syntax error');
           end;
    end;  (*case*)
  fracnum:
    case ch of
      '0'..'9' : begin
                 tokenstr:=tokenstr+ch;
                 getnextchar;
                 goto fracnum;
                 end;
      else begin
           if not inconsttable(tokenstr,ref) then
             begin
             insertconsttable(tokenstr);
             end;
           inserttoken('constant',ref);
           tokenstr:='';
           goto start;
           end;
    end;  (*case*)
  literal:
    dummy:=inlittable(tokenstr,ref);
    inserttoken('literal',ref);
    tokenstr:='';
    goto start;
  endline:
    inserttoken('endline',lines);
    lines:=lines+1;
    tokenstr:='';
    if ch=#26 then goto exit
              else goto start;
  exit:
  end;
 
Interesting.

Well, it wouldn't have passed a code-review by me anyway. I'd use while statements rather than things like
Code:
 wholenum:
    case ch of
      '0'..'9' : begin
                 tokenstr:=tokenstr+ch;
                 getnextchar;
                 goto wholenum;
and I believe it would be just as readable (if not better).

I won't even comment on the giant section of global variables (perhaps its a pascal thingie) as we'd get even more off-topic...



/Per
[sub]
&quot;It was a work of art, flawless, sublime. A triumph equaled only by its monumental failure.&quot;[/sub]
 
Thanks Salem, Per, Ion, etc for your opinions.

I think I'll just stick with my static method... ;)
 
> I dare you to do a
> LOG(i++)
> for some int i and predict the result.

The initial reason to invent LOG macro were not runtime calculations but compilation time allocation of array boundaries. Of course, it should be used exceptionally with #define constants as its arguments.
 
mingis, you're kidding.
Let's suppose a macros based application. How would you maintain your macroses working correctly in a big application? You're creating a rule for code generation. A compile time rule... Is it a programming rule? If yes, how will you debug a macros ...:( Moreover, supposing the programing environment has possibility to debug macros, what would you do with program readability ??? And why not just to write the code or to write a function ?? So, in big applications you can not rely on macros logics at all. That things what comes only with experience. I saw many people what has big collection of macroses, continue to invent then but after a month don't use them. This collection grow rapidly(macroses + macros based macroses and so on), but after a year this person hate macroses and maybe keeps a copy somewhere, for history, but don't use them anymore.
At the end, you should know strictly where to apply macroses:
1. avoid of double including of headers
2. make different versions of code for different platforms (I mean there operation system, compiller as well as different country specifics)
3. defining constants. But there macroses become dangerous, better is to use const.
4. portability of code. There also macroses become dangerous.

Ion Filipski
1c.bmp
 
Fully aggree.

I'm using macroses with parameters for defining of dialog window controls layout and window size depending on amount of controls and theyr individual size (I don't like resources), and, you are right, it is quite hard to manage them.

> 2. make different versions of code for different platforms
> (I mean there operation system, compiller as well as
> different country specifics)
> 4. portability of code. There also macroses become dangerous

What do you mean under "portability of code" in topic 4.? Is that something else than 2.?
 
4 is very similar to 2.
But using #define for code portability usualy means to define types
for example
for older VisualC++

#define wchar_t unsigned char
for newest VisualC++ wchar_t is native type(could be not native but by default is native), for borlandC++ is also native type. For both you make some #define WCHAR ....
But this is quite the same construction as
#ifdef __BORLANDC__
# include<iostream.h>
#else
# include<iostream>
using namespace std;
#endif


Ion Filipski
1c.bmp
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top