Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #18997 > unrolled thread
| Started by | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| First post | 2012-03-24 11:57 +0000 |
| Last post | 2012-03-26 00:54 -0700 |
| Articles | 20 on this page of 46 — 20 participants |
Back to article view | Back to comp.lang.c
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 →
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2012-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]
| From | jacob navia <jacob@spamsink.net> |
|---|---|
| Date | 2012-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2012-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]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2012-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]
| From | jacob navia <jacob@spamsink.net> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2012-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]
| From | Kaz Kylheku <kaz@kylheku.com> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | jacob navia <jacob@spamsink.net> |
|---|---|
| Date | 2012-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2012-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-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]
| From | ImpalerCore <jadill33@gmail.com> |
|---|---|
| Date | 2012-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]
| From | "io_x" <a@b.c.invalid> |
|---|---|
| Date | 2012-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]
| From | "io_x" <a@b.c.invalid> |
|---|---|
| Date | 2012-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]
| From | "io_x" <a@b.c.invalid> |
|---|---|
| Date | 2012-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]
| From | pete <pfiland@mindspring.com> |
|---|---|
| Date | 2012-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]
| From | pete <pfiland@mindspring.com> |
|---|---|
| Date | 2012-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]
| From | "io_x" <a@b.c.invalid> |
|---|---|
| Date | 2012-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]
| From | William Ahern <william@wilbur.25thandClement.com> |
|---|---|
| Date | 2012-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