Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #18997 > unrolled thread

template metaprogramming in C?

Started byRui Maciel <rui.maciel@gmail.com>
First post2012-03-24 11:57 +0000
Last post2012-03-26 00:54 -0700
Articles 20 on this page of 46 — 20 participants

Back to article view | Back to comp.lang.c


Contents

  template metaprogramming in C? Rui Maciel <rui.maciel@gmail.com> - 2012-03-24 11:57 +0000
    Re: template metaprogramming in C? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-24 07:25 -0700
      Re: template metaprogramming in C? Markus Wichmann <nullplan@gmx.net> - 2012-03-26 11:46 +0200
        Re: template metaprogramming in C? Philipp Klaus Krause <pkk@spth.de> - 2012-03-27 21:09 +0200
          Re: template metaprogramming in C? Markus Wichmann <nullplan@gmx.net> - 2012-03-28 09:25 +0200
            Re: template metaprogramming in C? James Kuyper <jameskuyper@verizon.net> - 2012-03-28 06:59 -0400
        Re: template metaprogramming in C? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-28 12:13 -0700
        Re: template metaprogramming in C? James Dow Allen <jdallen2000@yahoo.com> - 2012-04-01 02:47 -0700
    Re: template metaprogramming in C? Jens Gustedt <jens.gustedt@loria.fr> - 2012-03-24 18:01 +0100
    Re: template metaprogramming in C? Nobody <nobody@nowhere.com> - 2012-03-24 22:57 +0000
      Re: template metaprogramming in C? William Ahern <william@wilbur.25thandClement.com> - 2012-03-24 18:29 -0700
        Re: template metaprogramming in C? Ian Collins <ian-news@hotmail.com> - 2012-03-25 15:03 +1300
        Re: template metaprogramming in C? nick_keighley_nospam@hotmail.com - 2012-03-25 05:32 -0700
    Re: template metaprogramming in C? BGB <cr88192@hotmail.com> - 2012-03-24 17:02 -0700
    Re: template metaprogramming in C? jacob navia <jacob@spamsink.net> - 2012-03-25 01:21 +0100
      Re: template metaprogramming in C? Philipp Klaus Krause <pkk@spth.de> - 2012-03-27 21:17 +0200
        Re: template metaprogramming in C? jacob navia <jacob@spamsink.net> - 2012-03-28 11:10 +0200
          Re: template metaprogramming in C? Nils M Holm <news2009@t3x.org> - 2012-03-28 10:05 +0000
            Re: template metaprogramming in C? Willem <willem@toad.stack.nl> - 2012-03-28 13:36 +0000
              Re: template metaprogramming in C? Nils M Holm <news2009@t3x.org> - 2012-03-28 14:40 +0000
          Re: template metaprogramming in C? Kaz Kylheku <kaz@kylheku.com> - 2012-03-28 18:32 +0000
            Re: template metaprogramming in C? jacob navia <jacob@spamsink.net> - 2012-03-28 22:27 +0200
              Re: template metaprogramming in C? Kaz Kylheku <kaz@kylheku.com> - 2012-03-28 21:02 +0000
          Re: template metaprogramming in C? Nobody <nobody@nowhere.com> - 2012-03-29 16:30 +0100
            Re: template metaprogramming in C? jacob navia <jacob@spamsink.net> - 2012-03-29 23:39 +0200
              Re: template metaprogramming in C? "BartC" <bc@freeuk.com> - 2012-03-29 23:36 +0100
                Re: template metaprogramming in C? Kaz Kylheku <kaz@kylheku.com> - 2012-03-30 00:55 +0000
              Re: template metaprogramming in C? Kaz Kylheku <kaz@kylheku.com> - 2012-03-30 00:32 +0000
                Re: template metaprogramming in C? "BartC" <bc@freeuk.com> - 2012-03-30 10:52 +0100
                  Re: template metaprogramming in C? jacob navia <jacob@spamsink.net> - 2012-04-01 09:36 +0200
              Re: template metaprogramming in C? Ian Collins <ian-news@hotmail.com> - 2012-03-30 16:32 +1300
                Re: template metaprogramming in C? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-31 01:52 -0700
      Re: template metaprogramming in C? ImpalerCore <jadill33@gmail.com> - 2012-03-28 08:48 -0700
        Re: template metaprogramming in C? "io_x" <a@b.c.invalid> - 2012-04-05 12:18 +0200
          Re: template metaprogramming in C? "io_x" <a@b.c.invalid> - 2012-04-05 13:08 +0200
            Re: template metaprogramming in C? "io_x" <a@b.c.invalid> - 2012-04-05 13:36 +0200
              Re: template metaprogramming in C? pete <pfiland@mindspring.com> - 2012-04-06 18:43 -0400
                Re: template metaprogramming in C? pete <pfiland@mindspring.com> - 2012-04-06 19:20 -0400
        Re: template metaprogramming in C? "io_x" <a@b.c.invalid> - 2012-04-05 13:08 +0200
    Re: template metaprogramming in C? William Ahern <william@wilbur.25thandClement.com> - 2012-03-24 19:01 -0700
      Re: template metaprogramming in C? William Ahern <william@wilbur.25thandClement.com> - 2012-03-24 19:10 -0700
    Re: template metaprogramming in C? Ian Collins <ian-news@hotmail.com> - 2012-03-25 15:25 +1300
      Re: template metaprogramming in C? Rui Maciel <rui.maciel@gmail.com> - 2012-03-25 15:13 +0100
        Re: template metaprogramming in C? Ian Collins <ian-news@hotmail.com> - 2012-03-26 07:10 +1300
          Re: template metaprogramming in C? Rui Maciel <rui.maciel@gmail.com> - 2012-03-25 20:31 +0100
            Re: template metaprogramming in C? nick_keighley_nospam@hotmail.com - 2012-03-26 00:54 -0700

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#19115

FromKaz Kylheku <kaz@kylheku.com>
Date2012-03-28 18:32 +0000
Message-ID<20120328110920.211@kylheku.com>
In reply to#19097
On 2012-03-28, jacob navia <jacob@spamsink.net> wrote:
> Le 27/03/12 21:17, Philipp Klaus Krause a écrit :
>> On 25.03.2012 01:21, jacob navia wrote:
>>
>>>
>>> The direction I am going is to establish real compile time functions
>>> where you have a rich and controlled environment where you develop your
>>> meta-programs, instead of the incredible limited environment of
>>> templates where you do not have even an if statement!
>>>
>>> […]
>>
>> Looks a lot like macros in Scheme.
>>
>> Philipp
>>
>>
>
> ???
> Scheme macros have if/while statements that allow you to generate code 
> in loops?

In general, Lisp macros have been doing this since the 1960's.

Scheme macros are distinguished by pioneering lexical scoping with automatic
hygiene.  Macro code templates, into which arbitrary user code is inserted, can
simply declare local variables in a straightforward way; yet the inserted code
does not have visibility into these variables. A hidden renaming process
eliminates the potential for a clash.

Common Lisp macros are more "nuts-and-bolts"; hygiene is DIY, but with more
flexibilities.

The object system is based on macros: class defining, method defining.

The standard LOOP macro is an entire sublanguage for iteration, expanded by a
macro, and makes a good macro demo:

 (loop for x in '(1 2 3 5)
       summing (* x x) into sum-of-squares
       counting x into n
       finally (return (sqrt (/ sum-of-squares n))))

  -> 3.122499

View the (implementation-specific, not portable Lisp) expansion:

  (macroexpand '(loop for x in '(1 2 3 5)
                      summing (* x x) into sum-of-squares
                      counting x into n
                      finally (return (sqrt (/ sum-of-squares n)))))

  ->

  (MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
   (BLOCK NIL
    (LET ((#:LIST-8731 '(1 2 3 5)))
     (PROGN
      (LET ((X NIL))
       (LET ((N 0) (SUM-OF-SQUARES 0))
        (MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
         (TAGBODY SYSTEM::BEGIN-LOOP (WHEN (ENDP #:LIST-8731) (LOOP-FINISH))
          (SETQ X (CAR #:LIST-8731))
          (PROGN (SETQ SUM-OF-SQUARES (+ SUM-OF-SQUARES (* X X)))
           (WHEN X (INCF N)))
          (PSETQ #:LIST-8731 (CDR #:LIST-8731)) (GO SYSTEM::BEGIN-LOOP)
          SYSTEM::END-LOOP
          (MACROLET
           ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP)))
           (PROGN (RETURN (SQRT (/ SUM-OF-SQUARES N))))))))))))) ;

[toc] | [prev] | [next] | [standalone]


#19119

Fromjacob navia <jacob@spamsink.net>
Date2012-03-28 22:27 +0200
Message-ID<jkvs7i$m04$1@speranza.aioe.org>
In reply to#19115
Le 28/03/12 20:32, Kaz Kylheku a écrit :
> On 2012-03-28, jacob navia<jacob@spamsink.net>  wrote:
>> Le 27/03/12 21:17, Philipp Klaus Krause a écrit :
>>> On 25.03.2012 01:21, jacob navia wrote:
>>>
>>>>
>>>> The direction I am going is to establish real compile time functions
>>>> where you have a rich and controlled environment where you develop your
>>>> meta-programs, instead of the incredible limited environment of
>>>> templates where you do not have even an if statement!
>>>>
>>>> […]
>>>
>>> Looks a lot like macros in Scheme.
>>>
>>> Philipp
>>>
>>>
>>
>> ???
>> Scheme macros have if/while statements that allow you to generate code
>> in loops?
>
> In general, Lisp macros have been doing this since the 1960's.
>

OK, it is high time then that we get similar capabilities in C. :-)

Compile time functions can access the compiler environment in a 
controlled way. (Probably Scheme macros too). The practical usage is
that you can decide your container structure based on the 
characteristics of the object being stored, for instance.

Let's say you have a list. Instead of having a pointer to the data, you 
can check if sizeof(data) is less or equal than  sizeof(void *). If that 
is the case it is just much better to store the data directly in the 
space the pointer would occupy, saving sizeof(void *) bytes and
an indirection.

Etc. That is the idea.


[toc] | [prev] | [next] | [standalone]


#19122

FromKaz Kylheku <kaz@kylheku.com>
Date2012-03-28 21:02 +0000
Message-ID<20120328134032.915@kylheku.com>
In reply to#19119
On 2012-03-28, jacob navia <jacob@spamsink.net> wrote:
> Le 28/03/12 20:32, Kaz Kylheku a écrit :
>> In general, Lisp macros have been doing this since the 1960's.
>>
>
> OK, it is high time then that we get similar capabilities in C. :-)
>
> Compile time functions can access the compiler environment in a 
> controlled way. (Probably Scheme macros too). The practical usage is
> that you can decide your container structure based on the 
> characteristics of the object being stored, for instance.
>
> Let's say you have a list. Instead of having a pointer to the data, you 
> can check if sizeof(data) is less or equal than  sizeof(void *). If that 
> is the case it is just much better to store the data directly in the 
> space the pointer would occupy, saving sizeof(void *) bytes and
> an indirection.
>
> Etc. That is the idea.

There is a project called GCC MELT which provides a Lisp dialect for writing
plugins for GCC to do this type of stuff.

http://gcc-melt.org/

It doesn't seem like the easiest thing in the world to use.

http://gcc.gnu.org/wiki/MELT%20tutorial

The plugins you write are not really integrated into your program; they get
compiled into modules that go into the compiler (but I suppose it can be
close enough for some practical purposes).

[toc] | [prev] | [next] | [standalone]


#19136

FromNobody <nobody@nowhere.com>
Date2012-03-29 16:30 +0100
Message-ID<pan.2012.03.29.15.31.08.620000@nowhere.com>
In reply to#19097
On Wed, 28 Mar 2012 11:10:52 +0200, jacob navia wrote:

>> Looks a lot like macros in Scheme.
>>
>> Philipp
>>
>>
> 
> ???
> Scheme macros have if/while statements that allow you to generate code 
> in loops?

A Lisp macro is essentially a function which returns Lisp code (a
fundamental feature of Lisp is that code is data, making it ideal for
metaprogramming). When compiling Lisp functions, macros are expanded by
evaluating the macro body and compiling the returned code. Unlike normal
function calls, the macro's arguments are passed verbatim (as expressions)
rather than being evaluated first.

[toc] | [prev] | [next] | [standalone]


#19146

Fromjacob navia <jacob@spamsink.net>
Date2012-03-29 23:39 +0200
Message-ID<jl2kq2$isg$1@speranza.aioe.org>
In reply to#19136
Le 29/03/12 17:30, Nobody a écrit :
> On Wed, 28 Mar 2012 11:10:52 +0200, jacob navia wrote:
>
>>> Looks a lot like macros in Scheme.
>>>
>>> Philipp
>>>
>>>
>>
>> ???
>> Scheme macros have if/while statements that allow you to generate code
>> in loops?
>
> A Lisp macro is essentially a function which returns Lisp code (a
> fundamental feature of Lisp is that code is data, making it ideal for
> metaprogramming). When compiling Lisp functions, macros are expanded by
> evaluating the macro body and compiling the returned code. Unlike normal
> function calls, the macro's arguments are passed verbatim (as expressions)
> rather than being evaluated first.
>

Then, I am doing exactly that: A meta programming C function is a 
function that inputs text and outputs text. The text that is the input 
of the function is the stream of text that is before the compiler 
parsing point. The output of the meta-programming function is text that 
is inserted at the point of call into the compiler stream.

Note that the inserted text will generate further events that could
call further events functions.

Of course a meta-function doesn't need to generate text. It could just 
record some event for later use, for instance to give a list of all
objects defined in a compilation unit, or whatever.

[toc] | [prev] | [next] | [standalone]


#19147

From"BartC" <bc@freeuk.com>
Date2012-03-29 23:36 +0100
Message-ID<jl2o6o$gbe$1@dont-email.me>
In reply to#19146

"jacob navia" <jacob@spamsink.net> wrote in message 
news:jl2kq2$isg$1@speranza.aioe.org...
> Le 29/03/12 17:30, Nobody a écrit :

>> A Lisp macro is essentially a function which returns Lisp code (a
>> fundamental feature of Lisp is that code is data, making it ideal for
>> metaprogramming). When compiling Lisp functions, macros are expanded by
>> evaluating the macro body and compiling the returned code. Unlike normal
>> function calls, the macro's arguments are passed verbatim (as 
>> expressions)
>> rather than being evaluated first.
>>
>
> Then, I am doing exactly that: A meta programming C function is a function 
> that inputs text and outputs text. The text that is the input of the 
> function is the stream of text that is before the compiler parsing point. 
> The output of the meta-programming function is text that is inserted at 
> the point of call into the compiler stream.

C isn't known for it's text-processing abilities, but you're using it to 
transform one stream of text into another?

I'd imagine also that using the same language for the meta-programming as 
both the input and output languages, things could get a trifle confusing.

However it would be interesting to see how it works in practice.

-- 
Bartc

 

[toc] | [prev] | [next] | [standalone]


#19153

FromKaz Kylheku <kaz@kylheku.com>
Date2012-03-30 00:55 +0000
Message-ID<20120329171933.707@kylheku.com>
In reply to#19147
On 2012-03-29, BartC <bc@freeuk.com> wrote:
> I'd imagine also that using the same language for the meta-programming as 
> both the input and output languages, things could get a trifle confusing.

It only gets confusing if you do it right.

If the metaprogramming language is the same as the metaprogrammed language, but
the trees of the metaprogrammed language appear only as encapsulated data
structures, there is no such confusion. But that situation extremely
inconvenient.

Early Lisp metaprogramming was done by writing very clumsy code which analyzed
and constructed code. If you wanted to construct the expression (+ left right)
but where the left and right are pieces of code that you have in variables
x and y, something like (LIST '+ X Y). Make a list of out of the symbol +, and
the values of X and Y.

Then the backquote was invented which allowed code to be generated with a
constructor notation that much more closely resembles the language:

  `(+ ,x ,y)

You write the template as a literal: you quote a piece of the meta-programming
program with the backquote, and then you nidicate the variable parts with
unquotes and splices denoted by , and ,@.

Backquotes can nest, and occur in the unquotes and splices, so very complicated
situations can be hard to understand because of the level confusion: what is
meta and what isn't.

But the overwhelming convenience and notational clarity of backquote trumps
these issues. (And the confusion can be combated by refactoring code into
small functional chunks instead of nesting a whole lot of stuff in one place.)

You basically want the meta-language to be the same as the language precisely
so that you can just quote any construct in the meta-language to obtain a piece
of AST, into which you can substitute things.

It's easier because you're just dealing with one language, and then keeping in
mind what is in the metaprogram and what is in the program. (Or, sometimes,
what is in the meta-meta-program, what is in the meta-program and what is in
the program.)

It's easier to shift between these levels, too. Somtimes you put something into
the program being generated, but then later you want to hoist it back into the
metaprogram: i.e. make it a compile-time calculation. If the two languages
are the same, it's easy to do this while keeping most of the code the same,
or very similar.

Also, sometimes you want to evaluate parts of the meta-material at
macro-expansion time. This is easy if the language is the same: just pass the
tree to the built-in eval function. You don't need a separate eval function for
the target language.

Probably the main reason for using one language is that there are multiple
levels of metaprogramming, not only one. The meta-programming macros themselves
use macros, and those macros can be written using macros: i.e. the
meta-language is applied to itself to create better metaprogramming: it is
turned in on itself.  You don't want N different languages for N different
meta-levels; it's simply not practical, and not even possible when N is
unbounded.

[toc] | [prev] | [next] | [standalone]


#19151

FromKaz Kylheku <kaz@kylheku.com>
Date2012-03-30 00:32 +0000
Message-ID<20120329171146.904@kylheku.com>
In reply to#19146
On 2012-03-29, jacob navia <jacob@spamsink.net> wrote:
> Le 29/03/12 17:30, Nobody a écrit :
>> On Wed, 28 Mar 2012 11:10:52 +0200, jacob navia wrote:
>>
>>>> Looks a lot like macros in Scheme.
>>>>
>>>> Philipp
>>>>
>>>>
>>>
>>> ???
>>> Scheme macros have if/while statements that allow you to generate code
>>> in loops?
>>
>> A Lisp macro is essentially a function which returns Lisp code (a
>> fundamental feature of Lisp is that code is data, making it ideal for
>> metaprogramming). When compiling Lisp functions, macros are expanded by
>> evaluating the macro body and compiling the returned code. Unlike normal
>> function calls, the macro's arguments are passed verbatim (as expressions)
>> rather than being evaluated first.
>>
>
> Then, I am doing exactly that: A meta programming C function is a 
> function that inputs text and outputs text.

Then, you're doing it wrong. Firstly, C is one of the lousiest languages in the
world for metaprogramming.  If you want to do anything "meta" in C,
you don't want to do it in C. Lisp is used for metaprogramming Lisp, not
simply for the sake of making the metaprogramming language the same as
the meta-programmed language. The metaproramming happens because Lisp is an
excellent language for metaprogramming (which evoled along with the 
language right from the beginning).

Look at that GCC MELT project: they are not using C as the meta-programming
language, for good reasons.

Secondly, the Lisp macro is not a text to text mapping. It filters an AST 
data structure to to an AST data structure: it is tree to tree rewriting.  Text
to text mapping is the same as the C preprocessor, or tools like m4.  If you
just want text to text mapping that's better than the preprocessor, just pull
m4 off the shelf.  m4 has all that cruft missing from the C preprocessor, like
looping over lists of things, if/then/else decisions, etc.

[toc] | [prev] | [next] | [standalone]


#19160

From"BartC" <bc@freeuk.com>
Date2012-03-30 10:52 +0100
Message-ID<jl3vsv$5o2$1@dont-email.me>
In reply to#19151
"Stefan Ram" <ram@zedat.fu-berlin.de> wrote in message 
news:meta-20120330024837@ram.dialup.fu-berlin.de...
> Kaz Kylheku <kaz@kylheku.com> writes:
>>If you want to do anything "meta" in C,
>>you don't want to do it in C.

> #include <stdio.h>
>
> int main( void )
> { char const * const names[] ={ "maxi", "maxd" };
>  char const * const types[] ={ "int", "double" };
>  printf( "#include <stdio.h>\n\n" );
>  for( unsigned i = 0; i < sizeof types / sizeof 0[ types ]; ++i )
>  { char const * type = i[ types ];
>    printf
>    ( "%s %s( %s const a, %s const b ){ return a > b ? a : b; }\n",
>      type, i[ names], type, type ); }
>  printf( "\nint main( void )\n" );
>  printf( "{ printf( \"%%d\\n\", maxi( 2, 3 ));\n" );
>  printf( "  printf( \"%%g\\n\", maxd( 2.0, 3.0 )); }\n" ); }
>
>  It contains the pattern "a > b ? a : b" to find a maximum and then
>  applies this pattern to the types of »int« and »double«.

Is this meta-programming, or just programming? It looks like something that 
would be run as an external utility, rather than a piece of meta-code 
encountered within a normal program, and the output of which is then 
available to the rest of the source code.

(And if run as an external program, then anything slightly more complex 
would be less painful to write with any scripting language.)

And even as a C meta-program, if shows the limitations of using C: you 
really want to loop through all the numeric types, and have access to the 
names of those types, as well as literals in each of those types, without 
having to manually enumerate each.

Try out a real task (which I have a use for myself, and currently use 
external utilities for, generating include files):

You have a number of functions in a module, some of which have textual 
meta-data (in the form of a stylised comment for example); scan those 
functions with a specific kind of meta-data, read the values listed in the 
metadata, and create a table (an initialised array of structs perhaps), 
containing pointers to those functions, the names of the functions, and the 
values for those functions.

And put the table at the location where the meta-program is encountered.

As an added bonus, create a list of prototype declarations suitable for 
adding to a header (not strictly necessary, as you might expect to create 
such prototypes yourself at the same time as you write each function).

(Actually, this is not very easy. It would require a separate pass of it's 
own from the compiler. It might get recursive, if the meta-program adds new 
functions which themselves have meta-data! Or if the meta-program generates 
a new version of itself. However, if this was possible, it would be great: 
forget my example; you can create a meta-program macro which automatically 
generates function prototypes for example.)

-- 
Bartc

 

[toc] | [prev] | [next] | [standalone]


#19195

Fromjacob navia <jacob@spamsink.net>
Date2012-04-01 09:36 +0200
Message-ID<jl90hk$lid$1@speranza.aioe.org>
In reply to#19160
Le 30/03/12 11:52, BartC a écrit :

> Try out a real task (which I have a use for myself, and currently use
> external utilities for, generating include files):
>
> You have a number of functions in a module, some of which have textual
> meta-data (in the form of a stylised comment for example); scan those
> functions with a specific kind of meta-data, read the values listed in
> the metadata, and create a table (an initialised array of structs
> perhaps), containing pointers to those functions, the names of the
> functions, and the values for those functions.
>

The "meta-comment" is the sequence /*@ */. This sequence generates an 
event that can be subclassed.

Your function  then, just parses the comment since all the input is 
available.

> And put the table at the location where the meta-program is encountered.
>

You generate code that builds those structures. Obviously you have to 
take care WHERE you put the meta comment, for instance you can't put it 
in the middle of an expression:

double d = (sqrt(s+3.14)/25/*@metacomment*/*m;

You can put it only in a place where a structure definition is possible, 
i.e. at the beginning of a statement.

> As an added bonus, create a list of prototype declarations suitable for
> adding to a header (not strictly necessary, as you might expect to
> create such prototypes yourself at the same time as you write each
> function).
>

Well, lcc can already parse a file and write the prototypes at the end 
of the compilation and I thought that in the meta-programming 
environment this could be just a function call away:

char *proto = MakeProto(function_type);

> (Actually, this is not very easy. It would require a separate pass of
> it's own from the compiler. It might get recursive, if the meta-program
> adds new functions which themselves have meta-data!

When code is injected into the compiler stream, the event that has fired 
is disabled, and the generated code can't generate the same event. It 
can generate OTHER events though.


> Or if the
> meta-program generates a new version of itself. However, if this was
> possible, it would be great: forget my example; you can create a
> meta-program macro which automatically generates function prototypes for
> example.)
>

Yes

[toc] | [prev] | [next] | [standalone]


#19157

FromIan Collins <ian-news@hotmail.com>
Date2012-03-30 16:32 +1300
Message-ID<9tknr2Fq3oU1@mid.individual.net>
In reply to#19146
On 03/30/12 10:39 AM, jacob navia wrote:
> Le 29/03/12 17:30, Nobody a écrit :
>> On Wed, 28 Mar 2012 11:10:52 +0200, jacob navia wrote:
>>
>>>> Looks a lot like macros in Scheme.
>>>>
>>>> Philipp
>>>>
>>>>
>>>
>>> ???
>>> Scheme macros have if/while statements that allow you to generate code
>>> in loops?
>>
>> A Lisp macro is essentially a function which returns Lisp code (a
>> fundamental feature of Lisp is that code is data, making it ideal for
>> metaprogramming). When compiling Lisp functions, macros are expanded by
>> evaluating the macro body and compiling the returned code. Unlike normal
>> function calls, the macro's arguments are passed verbatim (as expressions)
>> rather than being evaluated first.
>>
>
> Then, I am doing exactly that: A meta programming C function is a
> function that inputs text and outputs text. The text that is the input
> of the function is the stream of text that is before the compiler
> parsing point. The output of the meta-programming function is text that
> is inserted at the point of call into the compiler stream.

Is that meta-programming, or emulation the eval() function common to 
scripting languages?  Or is eval() meta-programming?


-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#19245

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2012-03-31 01:52 -0700
Message-ID<1219280.548.1333183970687.JavaMail.geo-discussion-forums@ynlp3>
In reply to#19157
בתאריך יום שישי, 30 במרס 2012 04:32:50 UTC+1, מאת Ian Collins:
> 
> Is that meta-programming, or emulation the eval() function common to 
> scripting languages?  Or is eval() meta-programming?
> 
> 
It's meta programming is you generate the string to be evaluated on the fly. If you hardcode it, it's just using an interpreted rather than a compiled language.

If the string is entered by the user, it raises the question of where the biundary lies between using an application and programming. Complex and flexible applications have a tendency to turn into programming languages in their own right.

-- 
MiniBasic - how to write a script interpter. Dip your toe into the meta-programming world.
http://www.malcolmmclean.site11.com/www

[toc] | [prev] | [next] | [standalone]


#19229

FromImpalerCore <jadill33@gmail.com>
Date2012-03-28 08:48 -0700
Message-ID<fd4f60c4-a447-47fe-94a6-b003918d88c2@fk28g2000vbb.googlegroups.com>
In reply to#19015
On Mar 24, 8:21 pm, jacob navia <ja...@spamsink.net> wrote:

[snip]

> Look, this is not just empty talk. I have added for instance the require
> and ensure statements of the Eiffel language to an experimental version
> of the compiler to implement the "Design by contract" paradigm.

I've played around with some kind of contract programming ideas.  I'm
curious what the benefits of your extensions are.  I would imagine
that you could incorporate some kind of automatic evaluation without
having to lace your code with explicit macros.

Here is an example based on a square root function.

\code
#include <stdio.h>
#include <clover/contract.h>

const double tolerance = 0.0000001;
const int max_iterations = 10;

double heron_sqrt( double x );

int main( void )
{
  size_t idx;
  char tmp_str[40];

  double input[] = {
    0, 1, 10, 100, 1000, 10000, 0.1, 0.25, -1
  };

  for ( idx = 0; idx < sizeof (input) / sizeof (input[0]); ++idx )
  {
    snprintf( tmp_str, sizeof (tmp_str), "sqrt( %.2f )", input[idx] );
    printf( "%-20s = %.10f\n", tmp_str, heron_sqrt( input[idx] ) );
  }

  return 0;
}

double heron_sqrt( double x )
{
  /*
   * The algorithm used to calculate the square root 'x' of number 'S'
   * is based on Heron's method.
   *
   * Let x(0) be an arbitrary positive number.
   * Let x(n+1) be the average of x(n) and 'S / x(n)'
   * Repeat until the desired accuracy is achieved.
   *
   * The closer x(0) is to the square root value, the fewer number
   * of iterations are needed to converge to the accuracy required.
   *
   * The global variable 'max_iterations' allows the person to
   * limit the accuracy of the result, which causes postcondition
   * violations.
   */

  double sqrt_x = 0;
  double guess = 0;
  double error = 0;
  int itr = 0;
  C_POST( double x_sq; )

  C_REQUIRE( x >= 0 );

  if ( x == 0.0 ) {
    sqrt_x = 0;
  }
  else
  {
    sqrt_x = x * 0.5;

    do
    {
      guess = sqrt_x;
      sqrt_x = 0.5 * ( guess + x / guess );
      error = sqrt_x * sqrt_x - x;
      error = error < 0 ? -error : error;
      ++itr;
    } while ( error > tolerance && itr < max_iterations );
  }

  C_POST( x_sq = sqrt_x * sqrt_x; )
  C_ENSURE( x_sq - tolerance <= x && x <= x_sq + tolerance );

  return sqrt_x;
}
\endcode

Since C does not support implicitly executed destructors, it's
unlikely that one would need to package it like the following.

\code
double heron_sqrt( double x )
{
  double sqrt_x = 0;
  C_POST( double x_sq; )

  C_REQUIRE( x >= 0 );

  sqrt_x = heron_sqrt_impl( x );

  C_POST( x_sq = sqrt_x * sqrt_x; )
  C_ENSURE( x_sq - tolerance <= x && x <= x_sq + tolerance );

  return sqrt_x;
}

double heron_sqrt_impl( double x )
{
  /*
   * The algorithm used to calculate the square root 'x' of number 'S'
   * is based on Heron's method.
   *
   * Let x(0) be an arbitrary positive number.
   * Let x(n+1) be the average of x(n) and 'S / x(n)'
   * Repeat until the desired accuracy is achieved.
   *
   * The closer x(0) is to the square root value, the fewer number
   * of iterations are needed to converge to the accuracy required.
   *
   * The global variable 'max_iterations' allows the person to
   * limit the accuracy of the result, which causes postcondition
   * violations.
   */

  double sqrt_x = 0;
  double guess = 0;
  double error = 0;
  int itr = 0;

  if ( x == 0.0 ) {
    sqrt_x = 0;
  }
  else
  {
    sqrt_x = x * 0.5;

    do
    {
      guess = sqrt_x;
      sqrt_x = 0.5 * ( guess + x / guess );
      error = sqrt_x * sqrt_x - x;
      error = error < 0 ? -error : error;
      ++itr;
    } while ( error > tolerance && itr < max_iterations );
  }

  return sqrt_x;
}
\endcode

In this scenario, one can limit the number of maximum iterations to
cause postcondition violations where the sqrt converges outside of the
defined tolerance.  And passing a negative value will cause a
precondition violation.

I get this output when max_iterations is 10.

\result
sqrt( 0.00 )         = 0.0000000000
sqrt( 1.00 )         = 1.0000000465
sqrt( 10.00 )        = 3.1622776604
sqrt( 100.00 )       = 10.0000000001
sqrt( 1000.00 )      = 31.6227766017
sqrt( 10000.00 )     = 100.0000000000
sqrt( 0.10 )         = 0.3162277669
sqrt( 0.25 )         = 0.5000000796
Precondition failed: x >= 0, file c_contract_sqrt_example.c, line 52,
function heron_sqrt
\endresult

If I set 'max_iterations' to 5, I get this.

\result
sqrt( 0.00 )         = 0.0000000000
sqrt( 1.00 )         = 1.0000000465
sqrt( 10.00 )        = 3.1622776604
Postcondition failed: x_sq - tolerance <= x && x <= x_sq + tolerance,
file c_contract_sqrt_example.c, line 72, function heron_sqrt
\endresult

Here is how I define the contract feature macros.

\code snippet
#if ( defined(C_CONTRACT_ENFORCE_PRECONDITIONS) ||  \
      defined(C_CONTRACT_ENFORCE_POSTCONDITIONS) || \
      defined(C_CONTRACT_ENFORCE_INVARIANTS) ||     \
      defined(C_CONTRACT_ENFORCE_ALL) )             \
    &&                                              \
      !defined(C_NO_CONTRACT_PRECONDITIONS)

/*!
 * \brief Declare a precondition-only evaluated statement.
 * \param statement The statement.
 */
#define C_PRE( statement ) statement

/*!
 * \brief Declare a precondition contract.
 * \param expr The expression.
 */
#define C_REQUIRE( expr )                                            \
  do                                                                 \
  {                                                                  \
    if ( expr ) {}                                                   \
    else                                                             \
    {                                                                \
      gc_signal_contract_violation( c_precondition_violation, #expr, \
                                    __FILE__, __LINE__, __func__ );  \
    }                                                                \
  } while(0)
#else

#define C_PRE( statement ) /* nothing */
#define C_REQUIRE( expr ) /* nothing */

#endif

#if ( defined(C_CONTRACT_ENFORCE_POSTCONDITIONS) || \
      defined(C_CONTRACT_ENFORCE_INVARIANTS) ||     \
      defined(C_CONTRACT_ENFORCE_ALL) )             \
    &&                                              \
      !defined(C_NO_CONTRACT_POSTCONDITIONS)

/*!
 * \brief Declare a postcondition-only evaluated statement.
 * \param statement The statement.
 */
#define C_POST( statement ) statement

/*!
 * \brief Declare a postcondition contract.
 * \param expr The expression.
 */
#define C_ENSURE( expr )
\
  do
\
 
{                                                                   \
    if ( expr ) {}
\
    else
\
 
{                                                                 \
      gc_signal_contract_violation( c_postcondition_violation, #expr,
\
                                    __FILE__, __LINE__, __func__ );
\
    }
\
  } while(0)

#else

#define C_POST( statement ) /* nothing */
#define C_ENSURE( expr ) /* nothing */

#endif
\endcode

If you were to write a version of sqrt using require/ensure, what
would it look like?

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#19352

From"io_x" <a@b.c.invalid>
Date2012-04-05 12:18 +0200
Message-ID<4f7d7070$0$1387$4fafbaef@reader2.news.tin.it>
In reply to#19229
"ImpalerCore" <jadill33@gmail.com> ha scritto nel messaggio
news:fd4f60c4-a447-47fe-94a6-b003918d88c2@fk28g2000vbb.googlegroups.com...
On Mar 24, 8:21 pm, jacob navia <ja...@spamsink.net> wrote:

[snip]

> Look, this is not just empty talk. I have added for instance the require
> and ensure statements of the Eiffel language to an experimental version
> of the compiler to implement the "Design by contract" paradigm.

I've played around with some kind of contract programming ideas.  I'm
curious what the benefits of your extensions are.  I would imagine
that you could incorporate some kind of automatic evaluation without
having to lace your code with explicit macros.
....
If you were to write a version of sqrt using require/ensure, what
would it look like?

Best regards,
John D.

#io_x start
it will look as:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// macro for types
#define  u64  uint64_t
#define  u32  uint32_t
#define  u16  uint16_t
#define  u8    uint8_t
#define  i64   int64_t
#define  i32   int32_t
#define  i16   int16_t
#define  i8     int8_t

// macro for keywords
#define   R    return
#define   P    printf
#define   F    for
#define   G    goto

/*
L=1/2(L+x/L)  => 2L=(L+x/L) => L=x/L => L^2=x => L=sqrt(x)
     v=p;
     F(i=((1==v)+v)/2; v>i; i=(p/v+v)/2)  v = i;
*/

// args: *r sqrt of p, ncs is the number of digit "significativi"
// if all ok return the number of cicles of the loop
// if not ok return 0
// NB on test r is a pointer to 2 double
//
u32  rsqrt(double*  r, double  p, u32  ncs)
{double  t, e, v;
 u32        i, h;
   if(r==0||p<0.0||ncs>0xFFFFFFF)
                 R   0;
   if(p==1.0||p==0.0)
          {*r=p; R   1;}

   // i claim seems ok sqrt(NdigitsAftherComma)
   e=ncs; h=sqrt(e);
   if(p>1.0)    --h;
   F(i=0, e=0.1; i<h && e!=0.0; ++i)
             e=e/10.0;
   i=1;
   v= p>=1.0? p: 1.0; // if p>1.0 => v=p   >sqrt(p) from above
                      // if p<1.0 => v=1.0 >sqrt(p) from above
// cancel "r[1]=v" if not test
x: t=(v+p/v)/2; if(v-t<=e){*r=t; r[1]=v; R  i;}
   v=t; ++i; G x;
}

u32  __stdcall FindNPrime(u32   pos);

// below main23 is +- from
// <fd4f60c4-a447-47fe-94a6-b003918d88c2@fk28g2000vbb.googlegroups.com>
// from "ImpalerCore"
int main23( void )
{double input[] = {0, 1, 10, 100, 1000, 10000, 0.1, 0.25, 0.001, 0.0001,
0.00001, -1};
 double            r[4];
 size_t           idx;
 u32                u;
 char    tmp_str[128];

 P("N cifre  2\n");
 for(idx=0; idx< sizeof(input)/sizeof(input[0]); ++idx )
  {snprintf( tmp_str, sizeof (tmp_str), "sqrt( %.8f )", input[idx] );
   u=rsqrt(&r[0],input[idx], 2);
   printf( "%-20s = %.10f  cicli=%u  r[1]=%.10f\n" , tmp_str, r[0], u, r[1]);
  }

 P("N cifre  6\n");
 for(idx=0; idx< sizeof(input)/sizeof(input[0]); ++idx )
  {snprintf( tmp_str, sizeof (tmp_str), "sqrt( %.8f )", input[idx] );
   u=rsqrt(&r[0],input[idx], 6);
   printf( "%-20s = %.10f  cicli=%u r[1]=%.10f\n" , tmp_str, r[0], u, r[1]);
  }

  return 0;
}

i don't know if loop will stop ... it would stop
if the sequence a_(n+1)=1/2(a_n+x/a_n)  converge to sqrt(x) ...

N cifre  2
sqrt( 0.00000000 )   = 0.0000000000  cicli=1  r[1]=0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1  r[1]=0.0000000000
sqrt( 10.00000000 )  = 3.1624556228  cicli=4  r[1]=3.1960050819
sqrt( 100.00000000 ) = 10.0000528956  cicli=6  r[1]=10.0325785110
sqrt( 1000.00000000 ) = 31.6227824507  cicli=8  r[1]=31.6420158687
sqrt( 10000.00000000 ) = 100.0000002549  cicli=10  r[1]=100.0071403871
sqrt( 0.10000000 )   = 0.3162455623  cicli=4  r[1]=0.3196005082
sqrt( 0.25000000 )   = 0.5000000232  cicli=4  r[1]=0.5001524390
sqrt( 0.00100000 )   = 0.0327452693  cicli=6  r[1]=0.0412454261
sqrt( 0.00010000 )   = 0.0116754739  cicli=7  r[1]=0.0177018070
sqrt( 0.00001000 )   = 0.0082345532  cicli=7  r[1]=0.0158377017
sqrt( -1.00000000 )  = 0.0082345532  cicli=0  r[1]=0.0158377017
N cifre  6
sqrt( 0.00000000 )   = 0.0000000000  cicli=1 r[1]=0.0158377017
sqrt( 1.00000000 )   = 1.0000000000  cicli=1 r[1]=0.0158377017
sqrt( 10.00000000 )  = 3.1622776652  cicli=5 r[1]=3.1624556228
sqrt( 100.00000000 ) = 10.0000000001  cicli=7 r[1]=10.0000528956
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9 r[1]=31.6227824507
sqrt( 10000.00000000 ) = 100.0000002549  cicli=10 r[1]=100.0071403871
sqrt( 0.10000000 )   = 0.3162277665  cicli=5 r[1]=0.3162455623
sqrt( 0.25000000 )   = 0.5000000232  cicli=4 r[1]=0.5001524390
sqrt( 0.00100000 )   = 0.0316227825  cicli=8 r[1]=0.0316420159
sqrt( 0.00010000 )   = 0.0100007140  cicli=9 r[1]=0.0101202184
sqrt( 0.00001000 )   = 0.0031720287  cicli=10 r[1]=0.0034205559
sqrt( -1.00000000 )  = 0.0031720287  cicli=0 r[1]=0.0034205559

#io_x end




[toc] | [prev] | [next] | [standalone]


#19355

From"io_x" <a@b.c.invalid>
Date2012-04-05 13:08 +0200
Message-ID<4f7d7c00$0$1374$4fafbaef@reader1.news.tin.it>
In reply to#19352
"io_x" <a@b.c.invalid> ha scritto nel messaggio 
news:4f7d7070$0$1387$4fafbaef@reader2.news.tin.it...
> u32  rsqrt(double*  r, double  p, u32  ncs)
> {double  t, e, v;
> u32        i, h;
>   if(r==0||p<0.0||ncs>0xFFFFFFF)
>                 R   0;
>   if(p==1.0||p==0.0)
>          {*r=p; R   1;}
>
>   // i claim seems ok sqrt(NdigitsAftherComma)
>   e=ncs; h=sqrt(e);
>   if(p>1.0)    --h;
>   F(i=0, e=0.1; i<h && e!=0.0; ++i)
>             e=e/10.0;
>   i=1;
>   v= p>=1.0? p: 1.0; // if p>1.0 => v=p   >sqrt(p) from above
>                      // if p<1.0 => v=1.0 >sqrt(p) from above
> // cancel "r[1]=v" if not test
> x: t=(v+p/v)/2; if(v-t<=e){*r=t; r[1]=v; R  i;}
>   v=t; ++i; G x;
> }

this should be wrong see the last post...

[toc] | [prev] | [next] | [standalone]


#19357

From"io_x" <a@b.c.invalid>
Date2012-04-05 13:36 +0200
Message-ID<4f7d82b9$0$1381$4fafbaef@reader2.news.tin.it>
In reply to#19355
"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4f7d7c00$0$1374$4fafbaef@reader1.news.tin.it...
>
> "io_x" <a@b.c.invalid> ha scritto nel messaggio
> news:4f7d7070$0$1387$4fafbaef@reader2.news.tin.it...
>> u32  rsqrt(double*  r, double  p, u32  ncs)
>> {double  t, e, v;
>> u32        i, h;
>>   if(r==0||p<0.0||ncs>0xFFFFFFF)
>>                 R   0;
>>   if(p==1.0||p==0.0)
>>          {*r=p; R   1;}
>>
>>   // i claim seems ok sqrt(NdigitsAftherComma)
>>   e=ncs; h=sqrt(e);
>>   if(p>1.0)    --h;
>>   F(i=0, e=0.1; i<h && e!=0.0; ++i)
>>             e=e/10.0;
>>   i=1;
>>   v= p>=1.0? p: 1.0; // if p>1.0 => v=p   >sqrt(p) from above
>>                      // if p<1.0 => v=1.0 >sqrt(p) from above
>> // cancel "r[1]=v" if not test
>> x: t=(v+p/v)/2; if(v-t<=e){*r=t; r[1]=v; R  i;}
>>   v=t; ++i; G x;
>> }
>
> this should be wrong see the last post...

this would be the last my post...

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

// macro for types
#define  u64  uint64_t
#define  u32  uint32_t
#define  u16  uint16_t
#define  u8    uint8_t
#define  i64   int64_t
#define  i32   int32_t
#define  i16   int16_t
#define  i8     int8_t

// macro for keywords
#define   R    return
#define   P    printf
#define   F    for
#define   G    goto

/*
L=1/2(L+x/L)  => 2L=(L+x/L) => L=x/L => L^2=x => L=sqrt(x)
     v=p;
     F(i=((1==v)+v)/2; v>i; i=(p/v+v)/2)  v = i;
*/

// args: *r sqrt of p, ncs is the number of digit "significativi"
// if all ok return the number of cicles of the loop
// if not ok return 0
// NB on test r is a pointer to 2 double
//
u32  rsqrt(double*  r, double  p, u32  ncs)
{double  t, e, v;
 u32           i;
   if(r==0||p<0.0||ncs>0xFFFFFFF)
                 R   0;
   if(p==1.0||p==0.0)
          {*r=p; R   1;}

   F(i=0, e=0.1; i<ncs && e!=0.0; ++i)
             e=e/10.0;
   i=1;
   v= p>=1.0? p: 1.0; // if p>1.0 => v=p   >sqrt(p) from above
                      // if p<1.0 => v=1.0 >sqrt(p) from above
x: t=(v+p/v)/2; if(v-t<=e){*r=t; R  i;}
   v=t; ++i; G x;
}

// below main23 is +- from
// <fd4f60c4-a447-47fe-94a6-b003918d88c2@fk28g2000vbb.googlegroups.com>
// from "ImpalerCore"
int main23( void )
{double input[] = {0, 1, 1.001, 2, 10, 100, 1000, 10000, 0.1, 0.25, 0.001,
0.0001, 0.00001, -1};
 double            r[4];
 size_t           idx;
 u32             u, i;
 char    tmp_str[128];


 F(i=0; i<10; ++i)
   {P("N cifre  %u\n", i);
    for(idx=0; idx< sizeof(input)/sizeof(input[0]); ++idx )
      {snprintf( tmp_str, sizeof (tmp_str), "sqrt( %.8f )", input[idx] );
       u=rsqrt(&r[0],input[idx], i);
       if(input[idx]>0)  r[3]=input[idx];
       else              r[3]=0;
       printf( "%-20s = %.10f  cicli=%u, %.10f, %.10f\n" ,
             tmp_str, r[0], u, r[1], r[3]=sqrt(r[3]) );
      }
   // P("\n");
  }
 return 0;
}

N cifre  0
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0005000000  cicli=1, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4166666667  cicli=2, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1624556228  cicli=4, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000528956  cicli=6, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227824507  cicli=8, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000002549  cicli=10, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3196005082  cicli=3, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5001524390  cicli=3, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0677253274  cicli=4, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0630303596  cicli=4, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0625531161  cicli=4, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0625531161  cicli=0, 0.0000000000, 0.0000000000
N cifre  1
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0005000000  cicli=1, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142156863  cicli=3, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776652  cicli=5, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000001  cicli=7, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000002549  cicli=10, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162455623  cicli=4, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000232  cicli=4, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0327452693  cicli=6, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0116754739  cicli=7, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0082345532  cicli=7, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0082345532  cicli=0, 0.0000000000, 0.0000000000
N cifre  2
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0005000000  cicli=1, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=4, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776652  cicli=5, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000001  cicli=7, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=11, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277665  cicli=5, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000232  cicli=4, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227825  cicli=8, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100007140  cicli=9, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031720287  cicli=10, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031720287  cicli=0, 0.0000000000, 0.0000000000
N cifre  3
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=2, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=4, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=6, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000001  cicli=7, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=11, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277665  cicli=5, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=5, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227825  cicli=8, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=10, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622926  cicli=11, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622926  cicli=0, 0.0000000000, 0.0000000000
N cifre  4
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=2, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=4, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=6, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000000  cicli=8, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=11, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277660  cicli=6, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=5, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227766  cicli=9, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=10, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622926  cicli=11, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622926  cicli=0, 0.0000000000, 0.0000000000
N cifre  5
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=2, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=5, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=6, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000000  cicli=8, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=10, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=11, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277660  cicli=6, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=5, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227766  cicli=9, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=10, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622777  cicli=12, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622777  cicli=0, 0.0000000000, 0.0000000000
N cifre  6
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=3, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=5, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=6, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000000  cicli=8, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=10, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=12, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277660  cicli=6, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=5, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227766  cicli=9, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=11, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622777  cicli=12, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622777  cicli=0, 0.0000000000, 0.0000000000
N cifre  7
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=3, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=5, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=6, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000000  cicli=8, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=10, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=12, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277660  cicli=6, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=6, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227766  cicli=9, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=11, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622777  cicli=13, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622777  cicli=0, 0.0000000000, 0.0000000000
N cifre  8
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=3, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=5, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=7, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000000  cicli=8, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=10, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=12, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277660  cicli=6, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=6, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227766  cicli=10, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=11, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622777  cicli=13, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622777  cicli=0, 0.0000000000, 0.0000000000
N cifre  9
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000, 1.0000000000
sqrt( 1.00100000 )   = 1.0004998751  cicli=3, 0.0000000000, 1.0004998751
sqrt( 2.00000000 )   = 1.4142135624  cicli=5, 0.0000000000, 1.4142135624
sqrt( 10.00000000 )  = 3.1622776602  cicli=7, 0.0000000000, 3.1622776602
sqrt( 100.00000000 ) = 10.0000000000  cicli=9, 0.0000000000, 10.0000000000
sqrt( 1000.00000000 ) = 31.6227766017  cicli=10, 0.0000000000, 31.6227766017
sqrt( 10000.00000000 ) = 100.0000000000  cicli=12, 0.0000000000, 100.0000000000
sqrt( 0.10000000 )   = 0.3162277660  cicli=7, 0.0000000000, 0.3162277660
sqrt( 0.25000000 )   = 0.5000000000  cicli=6, 0.0000000000, 0.5000000000
sqrt( 0.00100000 )   = 0.0316227766  cicli=10, 0.0000000000, 0.0316227766
sqrt( 0.00010000 )   = 0.0100000000  cicli=11, 0.0000000000, 0.0100000000
sqrt( 0.00001000 )   = 0.0031622777  cicli=13, 0.0000000000, 0.0031622777
sqrt( -1.00000000 )  = 0.0031622777  cicli=0, 0.0000000000, 0.0000000000

what about result? the last number of each line is the sys_sqrt(p)


[toc] | [prev] | [next] | [standalone]


#19417

Frompete <pfiland@mindspring.com>
Date2012-04-06 18:43 -0400
Message-ID<4F7F7185.2958@mindspring.com>
In reply to#19357
io_x wrote:

> u32  rsqrt(double*  r, double  p, u32  ncs)
 
> what about result? the last number of each line is the sys_sqrt(p)

If you want to compare the result of rsqrt(&r, p, ncs) to sqrt(p),

Then you should compare 
    (p / rsqrt(&r, p, ncs) - rsqrt(&r, p, ncs))
against
    (p / sqrt(p) - sqrt(p))

The expression with the smaller magnitude,
contains the more accurate square root function.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#19418

Frompete <pfiland@mindspring.com>
Date2012-04-06 19:20 -0400
Message-ID<4F7F7A2A.3303@mindspring.com>
In reply to#19417
pete wrote:
> 
> io_x wrote:
> 
> > u32  rsqrt(double*  r, double  p, u32  ncs)
> 
> > what about result? the last number of each line is the sys_sqrt(p)
> 
> If you want to compare the result of rsqrt(&r, p, ncs) to sqrt(p),
> 
> Then you should compare
>     (p / rsqrt(&r, p, ncs) - rsqrt(&r, p, ncs))
> against
>     (p / sqrt(p) - sqrt(p))
> 
> The expression with the smaller magnitude,
> contains the more accurate square root function.

/* BEGIN new.c output*/

square_root(0.000000) == 0.000000
       sqrt(0.000000) == 0.000000

square_root(1.000000) == 1.000000
       sqrt(1.000000) == 1.000000
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(1.001000) == 1.000500
       sqrt(1.001000) == 1.000500
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(2.000000) == 1.414214
       sqrt(2.000000) == 1.414214
x / square_root(x) - square_root(x) == 2.22045e-016
x /        sqrt(x) -        sqrt(x) == -2.22045e-016

square_root(10.000000) == 3.162278
       sqrt(10.000000) == 3.162278
x / square_root(x) - square_root(x) == 4.44089e-016
x /        sqrt(x) -        sqrt(x) == -4.44089e-016

square_root(100.000000) == 10.000000
       sqrt(100.000000) == 10.000000
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(1000.000000) == 31.622777
       sqrt(1000.000000) == 31.622777
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(10000.000000) == 100.000000
       sqrt(10000.000000) == 100.000000
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(0.100000) == 0.316228
       sqrt(0.100000) == 0.316228
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(0.250000) == 0.500000
       sqrt(0.250000) == 0.500000
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(0.001000) == 0.031623
       sqrt(0.001000) == 0.031623
x / square_root(x) - square_root(x) == 6.93889e-018
x /        sqrt(x) -        sqrt(x) == 6.93889e-018

square_root(0.000100) == 0.010000
       sqrt(0.000100) == 0.010000
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

square_root(0.000010) == 0.003162
       sqrt(0.000010) == 0.003162
x / square_root(x) - square_root(x) == 0
x /        sqrt(x) -        sqrt(x) == 0

/* END new.c output*/




/* BEGIN new.c */

#include <stdio.h>
#include <math.h>

double square_root(double x)
{
    double root = x;

    if (root > 0) {
        double next = root / 2 + 0.5;

        do {
            root = next;
            next = (x / root + root) / 2;
        } while (root > next);
    }
    return root;
}

int 
main(void)
{
    double input[] = {
        0, 1, 1.001, 2, 10, 100, 1000, 10000, 
        0.1, 0.25, 0.001, 0.0001, 0.00001
    };
    size_t x;

    puts("/* BEGIN new.c output*/\n");
    for (x = 0; x != sizeof input / sizeof *input; ++x) {
        printf("square_root(%f) == %f\n", input[x], 
            square_root(input[x]));
        printf("       sqrt(%f) == %f\n", input[x], 
            sqrt(input[x]));
        if (input[x] > 0) {
        printf("x / square_root(x) - square_root(x) == %g\n",
            input[x] / square_root(input[x])
            - square_root(input[x]));
        printf("x /        sqrt(x) -        sqrt(x) == %g\n\n",
            input[x] / sqrt(input[x]) - sqrt(input[x]));
        } else {
            putchar('\n');
        }
    }
    puts("/* END new.c output*/");
    return 0;
}

/* END new.c */

-- 
pete

[toc] | [prev] | [next] | [standalone]


#19356

From"io_x" <a@b.c.invalid>
Date2012-04-05 13:08 +0200
Message-ID<4f7d7c14$0$1391$4fafbaef@reader1.news.tin.it>
In reply to#19229
"ImpalerCore" <jadill33@gmail.com> ha scritto nel messaggio
news:fd4f60c4-a447-47fe-94a6-b003918d88c2@fk28g2000vbb.googlegroups.com...

what about...
// args: *r sqrt of p, ncs is the number of digit "significativi"
// if all ok return the number of cicles of the loop
// if not ok return 0
// NB on test r is a pointer to 2 double
//
u32  rsqrt(double*  r, double  p, u32  ncs)
{double  t, e, v;
 u32        i, h;
   if(r==0||p<0.0||ncs>0xFFFFFFF)
                 R   0;
   if(p==1.0||p==0.0)
          {*r=p; R   1;}

   if(p>=1.1)      h=sqrt(ncs);
   else if(ncs>2)  h=ncs/2;
   else            h=ncs;

   F(i=0, e=0.1; i<h && e!=0.0; ++i)
             e=e/10.0;
   i=1;
   v= p>=1.0? p: 1.0; // if p>1.0 => v=p   >sqrt(p) from above
                      // if p<1.0 => v=1.0 >sqrt(p) from above
x: t=(v+p/v)/2; if(v-t<=e){*r=t; r[1]=v; R  i;}
   v=t; ++i; G x;
}
N cifre  2
sqrt( 0.00000000 )   = 0.0000000000  cicli=1, 0.0000000000
sqrt( 1.00000000 )   = 1.0000000000  cicli=1, 0.0000000000
sqrt( 1.00100000 )   = 1.0005000000  cicli=1, 1.0010000000
sqrt( 2.00000000 )   = 1.4142156863  cicli=3, 1.4166666667
sqrt( 10.00000000 )  = 3.1622776652  cicli=5, 3.1624556228
sqrt( 100.00000000 ) = 10.0000000001  cicli=7, 10.0000528956
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9, 31.6227824507
sqrt( 10000.00000000 ) = 100.0000002549  cicli=10, 100.0071403871
sqrt( 0.10000000 )   = 0.3162277665  cicli=5, 0.3162455623
sqrt( 0.25000000 )   = 0.5000000232  cicli=4, 0.5001524390
sqrt( 0.00100000 )   = 0.0316227825  cicli=8, 0.0316420159
sqrt( 0.00010000 )   = 0.0100007140  cicli=9, 0.0101202184
sqrt( 0.00001000 )   = 0.0031720287  cicli=10, 0.0034205559
sqrt( -1.00000000 )  = 0.0031720287  cicli=0, 0.0034205559
N cifre  6
sqrt( 0.00000000 )   = 0.0000000000  cicli=1 0.0034205559
sqrt( 1.00000000 )   = 1.0000000000  cicli=1 0.0034205559
sqrt( 1.00100000 )   = 1.0004998751  cicli=2 1.0005000000
sqrt( 2.00000000 )   = 1.4142135624  cicli=4 1.4142156863
sqrt( 10.00000000 )  = 3.1622776652  cicli=5 3.1624556228
sqrt( 100.00000000 ) = 10.0000000001  cicli=7 10.0000528956
sqrt( 1000.00000000 ) = 31.6227766017  cicli=9 31.6227824507
sqrt( 10000.00000000 ) = 100.0000000000  cicli=11 100.0000002549
sqrt( 0.10000000 )   = 0.3162277665  cicli=5 0.3162455623
sqrt( 0.25000000 )   = 0.5000000000  cicli=5 0.5000000232
sqrt( 0.00100000 )   = 0.0316227825  cicli=8 0.0316420159
sqrt( 0.00010000 )   = 0.0100000000  cicli=10 0.0100007140
sqrt( 0.00001000 )   = 0.0031622926  cicli=11 0.0031720287
sqrt( -1.00000000 )  = 0.0031622926  cicli=0 0.0031720287



[toc] | [prev] | [next] | [standalone]


#19018

FromWilliam Ahern <william@wilbur.25thandClement.com>
Date2012-03-24 19:01 -0700
Message-ID<nta249-mj3.ln1@wilbur.25thandClement.com>
In reply to#18997
Rui Maciel <rui.maciel@gmail.com> wrote:
> What are your thoughts on adding a standard form of proper template 
> metaprogramming to the C programming language? 

There are three things you can use to get the job done most of the time,
IMO:

	1) Variable argument macros from C99,

	2) _Restrict from C11, and

	3) typeof operator (supported by most common compilers, including
	   MSC, GCC, clang, IBM XL, and Sun Studio)

_Restrict is documented in the C11 standard and there's discussion of it in
the comp.lang.c and comp.std.c archives.

The typeof operator was rejected by the committee in the 1990s, and their
reasons for doing so (namely, that parametrized typing is unnecessary)
strongly suggest they'd frown on adding something much more sophisticated.

The use of C99 variable argument macros to count parameters was shown by
Laurent Deniau in this group 6 years ago. Here's an example:

#include <stdio.h>

static void foo3() { puts(__func__); }
static void foo2() { puts(__func__); }
static void foo1() { puts(__func__); }

#define foo(...) PP_CALL(foo, __VA_ARGS__)

#define PP_NARG_(a, b, c, d, e, f, g, h, N,...) N
#define PP_NARG(...) PP_NARG_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define PP_CALL_(F, ...) F(__VA_ARGS__)
#define PP_CALL(F, ...) PP_CALL_(PP_XPASTE(F, PP_NARG(__VA_ARGS__)), __VA_ARGS__)
#define PP_PASTE(x, y) x##y
#define PP_XPASTE(x, y) PP_PASTE(x, y)

int main(void) {
	foo(1, 2, 3);
	foo(1, 2);
	foo(1);

	return 0;
} /* main() */

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web