Generics in C

Discussion in 'C Programming' started by ttl_idiot@yahoo.com, Jan 13, 2007.

  1. Guest

    This post is about how to get generic modules in a C environment. The
    aim is to get close to Ada generics. Using C++ is not an option. It
    should all run in a simple C compiler.

    When I think of a generic module, it is something that can be used
    exactly as it is. The generic H-file and/or C-file, should not have to
    be edited AT ALL in order to use it. If it has to be changed in just 1
    line, it could possibly still have great reusability properties, but it
    is not generic in the sense I mean.

    I am going to give a suggestion for a way to do generics, by presenting
    5 files as an example. I would very much like comments on how things
    could be simplified or extended, but still using only C.

    Ok, here we go. Lets say, we want to implement generic powers, by
    repeating multiplication. The user of the module have to provide the
    type, and a function that performs multiplication on that type.

    The generic module is represented by GenPower.h and GenPower.c. The
    instantiation module is My.h and My.c, and then we have a test program.
    The test program will calculate 3^5 = 3*3*3*3*3 = 243. It is compiled
    and run in VC6.

    Running the test program prints this to stdout:
    Result of power = 243

    Let me know what you think of the idea. Good? Bad? Old?
    Complicated? (In that case I agree, but I think it is worth it.)


    // File GENPOWER.H
    // Formal Generic Parameters:
    // INSTANCE The name of the instance module.
    // ATYPE The instance type.
    // (INSTANCE)_Multiply Multiplication function for the type.
    // (See prototype below for details.)
    //
    // void INSTANCE_Multiply(ATYPE *, ATYPE);
    // is implemented in your module, otherwise it will be
    // missed at link time.
    //
    // Details of formal parameter functions:
    #define MODULE_Multiply INSTANCE()##_Multiply
    void MODULE_Multiply(ATYPE *first_operand_and_result, ATYPE
    other_operand);
    //
    // Package: (What this module provides generically)
    #define MODULE_Power INSTANCE()##_Power
    void MODULE_Power (ATYPE *result, int exponent);
    //
    // End of file


    // File GENPOWER.C
    // This is just for #include -ing, Do not link this module.
    #include "GenPower.h"
    void MODULE_Power (ATYPE *result, int exponent)
    { // Exponent must be at least 1.
    ATYPE a;
    int i;
    a = *result;
    for (i=1; i<exponent; i++) {
    MODULE_Multiply (result, a);
    }
    }


    // File MY.H
    typedef unsigned long MYTYPE;
    // Ok, now we have declared our type, lets get the power function
    // by instantiating the generic power module:
    #define INSTANCE() MY
    #define ATYPE MYTYPE
    #include "GenPower.H"
    //
    void MY_Multiply(MYTYPE *, MYTYPE);
    // End of file


    // File MY.C
    #include "my.h"
    #include "genpower.c"
    // Yes we are including the C file, not the H file.
    // That way we actually get an implementation of the function
    // void MYTYPE_Power(MYTYPE *, int) right here in this module.
    // Of course, we also have to provide the multiplication function:
    void MY_Multiply(MYTYPE *first_operand_and_result, MYTYPE
    other_operand)
    {
    // Do something multiplicatish.
    (*first_operand_and_result) *= other_operand;
    }
    // End of file


    // Test program
    #include <stdio.h>
    #include "my.h"
    int main(int argc, char* argv[])
    {
    MYTYPE a;
    a = 3;
    MY_Power(&a, 5);
    printf ("Result of power = %d\n", (int) a);
    return 0;
    }
    // End of file
     
    , Jan 13, 2007
    #1
    1. Advertising

  2. santosh Guest

    wrote:
    > This post is about how to get generic modules in a C environment. The
    > aim is to get close to Ada generics. Using C++ is not an option. It
    > should all run in a simple C compiler.
    >
    > When I think of a generic module, it is something that can be used
    > exactly as it is. The generic H-file and/or C-file, should not have to
    > be edited AT ALL in order to use it. If it has to be changed in just 1
    > line, it could possibly still have great reusability properties, but it
    > is not generic in the sense I mean.
    >
    > I am going to give a suggestion for a way to do generics, by presenting
    > 5 files as an example. I would very much like comments on how things
    > could be simplified or extended, but still using only C.
    >
    > Ok, here we go. Lets say, we want to implement generic powers, by
    > repeating multiplication. The user of the module have to provide the
    > type, and a function that performs multiplication on that type.


    In my opinion, that defeats the purpose of generic programming.

    <snip>
     
    santosh, Jan 13, 2007
    #2
    1. Advertising

  3. Guest

    santosh wrote:
    > wrote:
    > > This post is about how to get generic modules in a C environment. The
    > > aim is to get close to Ada generics. Using C++ is not an option. It
    > > should all run in a simple C compiler.
    > >
    > > When I think of a generic module, it is something that can be used
    > > exactly as it is. The generic H-file and/or C-file, should not have to
    > > be edited AT ALL in order to use it. If it has to be changed in just 1
    > > line, it could possibly still have great reusability properties, but it
    > > is not generic in the sense I mean.
    > >
    > > I am going to give a suggestion for a way to do generics, by presenting
    > > 5 files as an example. I would very much like comments on how things
    > > could be simplified or extended, but still using only C.
    > >
    > > Ok, here we go. Lets say, we want to implement generic powers, by
    > > repeating multiplication. The user of the module have to provide the
    > > type, and a function that performs multiplication on that type.

    >
    > In my opinion, that defeats the purpose of generic programming.


    The purpose of generics is to write algorithms once, and allow them to
    apply to different types. The OP's proposal is not as general as it
    could be, but it is *one* form of generic programming. I give another
    more general approach in the following examples:

    http://www.pobox.com/~qed/ll.zip
    http://www.pobox.com/~qed/gstack.zip

    --
    Paul Hsieh
    http://www.pobox.com/~qed/
    http://bstring.sf.net/
     
    , Jan 13, 2007
    #3
  4. "santosh" <> writes:
    > wrote:

    [...]
    >> Ok, here we go. Lets say, we want to implement generic powers, by
    >> repeating multiplication. The user of the module have to provide the
    >> type, and a function that performs multiplication on that type.

    >
    > In my opinion, that defeats the purpose of generic programming.
    >
    > <snip>


    I disagree. It would be nice if the generic module could infer the
    appropriate multiplication operator given the type (<OT>as Ada
    generics can do</OT>), but that's difficult or impossible to do in C.

    Note also that it doesn't just *require* you to provide a
    multiplication function, it *allows* you to do so. If you provide a
    function that performs addition, the generic will perform
    multiplication. It provides a generic way to specify applying some
    arbitrary operation repeatedly. In a sense, that's more generic than
    just providing a power function.

    (I haven't read the code closely enough to verify that this will
    actually work.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 13, 2007
    #4
  5. "Keith Thompson" <> wrote in message
    >
    > I disagree. It would be nice if the generic module could infer the
    > appropriate multiplication operator given the type (<OT>as Ada
    > generics can do</OT>), but that's difficult or impossible to do in C.
    >
    > Note also that it doesn't just *require* you to provide a
    > multiplication function, it *allows* you to do so. If you provide a
    > function that performs addition, the generic will perform
    > multiplication. It provides a generic way to specify applying some
    > arbitrary operation repeatedly. In a sense, that's more generic than
    > just providing a power function.
    >
    > (I haven't read the code closely enough to verify that this will
    > actually work.)
    >

    Part of the solution is to have a few types as possible muddying typespace.

    However there are some basic functions that most generic operators need.
    Namely clone, copy, destroy, serialise, deserialise, print as human-readable
    string.

    Maths operators are a bit of a red herring. It is nice in theory to
    implement an average that works on huge integers and complex types. In
    practise, it is easy enough to roll your own, because the need doesn't arise
    sufficiently often. In any case, there are problems inherent in the
    process - the average of a list of integers is a real, for instance, so what
    is the average of a list of huge integers supposed to be?.
     
    Malcolm McLean, Jan 13, 2007
    #5
  6. Ian Collins Guest

    wrote:
    > // File MY.H
    > typedef unsigned long MYTYPE;
    > // Ok, now we have declared our type, lets get the power function
    > // by instantiating the generic power module:
    > #define INSTANCE() MY
    > #define ATYPE MYTYPE
    > #include "GenPower.H"
    > //
    > void MY_Multiply(MYTYPE *, MYTYPE);
    > // End of file
    >
    >
    > // File MY.C
    > #include "my.h"
    > #include "genpower.c"
    > // Yes we are including the C file, not the H file.
    > // That way we actually get an implementation of the function
    > // void MYTYPE_Power(MYTYPE *, int) right here in this module.
    > // Of course, we also have to provide the multiplication function:
    > void MY_Multiply(MYTYPE *first_operand_and_result, MYTYPE
    > other_operand)
    > {
    > // Do something multiplicatish.
    > (*first_operand_and_result) *= other_operand;
    > }
    > // End of file
    >
    >
    > // Test program
    > #include <stdio.h>
    > #include "my.h"


    What happens if you want to work with more than one type? my.h has
    already defined INSTANCE() and MTYPE.

    > int main(int argc, char* argv[])
    > {
    > MYTYPE a;
    > a = 3;
    > MY_Power(&a, 5);
    > printf ("Result of power = %d\n", (int) a);
    > return 0;
    > }
    > // End of file
    >



    --
    Ian Collins.
     
    Ian Collins, Jan 13, 2007
    #6
  7. In article <>,
    <> wrote:
    >This post is about how to get generic modules in a C environment. The
    >aim is to get close to Ada generics. Using C++ is not an option. It
    >should all run in a simple C compiler.


    [...]

    >Let me know what you think of the idea. Good? Bad? Old?
    >Complicated? (In that case I agree, but I think it is worth it.)


    Unnecessarily complicated.

    Comment #1: If you want {C++|Ada|whatever}, you know where to find it.
    Comment #2: What's wrong with a qsort-style interface?


    dave

    --
    Dave Vandervies

    English was never my strong point.
    --Richard Heathfield in comp.lang.c
     
    Dave Vandervies, Jan 14, 2007
    #7
  8. Guest

    > What happens if you want to work with more than one type? my.h has
    > already defined INSTANCE() and MTYPE.


    Good question. I get 2 warnings. One for redefining INSTANCE() and one
    for redefining ATYPE. But it compiles and gives the correct result. And
    I can't #undef them in the end of GenPower.h. Hmm.
     
    , Jan 14, 2007
    #8
  9. CBFalconer Guest

    Dave Vandervies wrote:
    > <> wrote:
    >
    >> This post is about how to get generic modules in a C environment.
    >> The aim is to get close to Ada generics. Using C++ is not an
    >> option. It should all run in a simple C compiler.

    >
    > [...]
    >
    >> Let me know what you think of the idea. Good? Bad? Old?
    >> Complicated? (In that case I agree, but I think it is worth it.)

    >
    > Unnecessarily complicated.
    >
    > Comment #1: If you want {C++|Ada|whatever}, you know where to find it.
    > Comment #2: What's wrong with a qsort-style interface?


    Take a look at how hashlib handles generic structures for storing,
    access, etc. It needs nothing unusual or questionable.
    Dog-standard C.

    <http://cbfalconer.home.att.net/download/>

    --
    "I conclude that there are two ways of constructing a software
    design: One way is to make it so simple that there are obviously
    no deficiencies and the other way is to make it so complicated
    that there are no obvious deficiencies." -- C. A. R. Hoare
     
    CBFalconer, Jan 14, 2007
    #9
  10. In article <>,
    Malcolm McLean <> wrote:

    >Maths operators are a bit of a red herring. It is nice in theory to
    >implement an average that works on huge integers and complex types. In
    >practise, it is easy enough to roll your own, because the need doesn't arise
    >sufficiently often.


    Taking an average is something that is easy to get wrong: as soon as
    you are working with floating point types (including those buried
    in a complex), you need to sort the values before doing the additions,
    because otherwise you risk losing precision and risk other numeric
    sins.

    There are a bunch of common algorithms that people -think-
    "are easy enough to roll your own", but really aren't. And so few people
    invest in Knuth these days :(
    --
    "No one has the right to destroy another person's belief by
    demanding empirical evidence." -- Ann Landers
     
    Walter Roberson, Jan 14, 2007
    #10
  11. "Walter Roberson" <-cnrc.gc.ca> wrote in message
    > In article <>,
    > Malcolm McLean <> wrote:
    >
    >>Maths operators are a bit of a red herring. It is nice in theory to
    >>implement an average that works on huge integers and complex types. In
    >>practise, it is easy enough to roll your own, because the need doesn't
    >>arise
    >>sufficiently often.

    >
    > Taking an average is something that is easy to get wrong: as soon as
    > you are working with floating point types (including those buried
    > in a complex), you need to sort the values before doing the additions,
    > because otherwise you risk losing precision and risk other numeric
    > sins.
    >
    > There are a bunch of common algorithms that people -think-
    > "are easy enough to roll your own", but really aren't. And so few people
    > invest in Knuth these days :(
    >

    If you are writing a general-purpose, resuable, high quality average routine
    then, yes, sorting by magnitude is one thing you can do to ensure maximum
    precision.
    For the vast majority of applications there is no need to do this, so "roll
    your own" can be better.
     
    Malcolm McLean, Jan 14, 2007
    #11
  12. "CBFalconer" <> wrote in message
    > Dave Vandervies wrote:
    >> <> wrote:
    >>
    >>> This post is about how to get generic modules in a C environment.
    >>> The aim is to get close to Ada generics. Using C++ is not an
    >>> option. It should all run in a simple C compiler.

    >>
    >> [...]
    >>
    >>> Let me know what you think of the idea. Good? Bad? Old?
    >>> Complicated? (In that case I agree, but I think it is worth it.)

    >>
    >> Unnecessarily complicated.
    >>
    >> Comment #1: If you want {C++|Ada|whatever}, you know where to find it.
    >> Comment #2: What's wrong with a qsort-style interface?

    >
    > Take a look at how hashlib handles generic structures for storing,
    > access, etc. It needs nothing unusual or questionable.
    > Dog-standard C.
    >
    > <http://cbfalconer.home.att.net/download/>
    >

    Take a look at my simulated annealing code
    http://www.personal.leeds.ac.uk/~bgy1mm

    it is also generic, but I am not happy with it. The problem is that the
    caller has to know how to implement all the functions, and what to do with
    the global pointer. All very fiddly. Obviously I want anneal(void *obj,
    double (*score)(void *), void (*mutate)(void *)), not lots of housekeeping
    parameters.
     
    Malcolm McLean, Jan 14, 2007
    #12
  13. Guest

    > <> wrote:
    > >This post is about how to get generic modules in a C environment. The
    > >aim is to get close to Ada generics. Using C++ is not an option. It
    > >should all run in a simple C compiler.

    >
    > [...]


    Dave Vandervies wrote:
    > [...]
    > Comment #2: What's wrong with a qsort-style interface?


    It is not close to Ada, and the style only works for functions, not for
    modules. (?)

    I don't like function pointers. Anyway, the hardware we use makes it
    impossible to use function pointers. It has to do with fixed adresses
    for variables that would normally be on the stack, and a very small
    RAM.

    > English was never my strong point.
    > --Richard Heathfield in comp.lang.c


    Mine either.
     
    , Jan 15, 2007
    #13
  14. santosh Guest

    wrote:
    > > English was never my strong point.
    > > --Richard Heathfield in comp.lang.c

    >
    > Mine either.


    Shouldn't this be 'Mine neither'?
     
    santosh, Jan 15, 2007
    #14
  15. santosh said:

    > wrote:
    >> > English was never my strong point.
    >> > --Richard Heathfield in comp.lang.c

    >>
    >> Mine either.

    >
    > Shouldn't this be 'Mine neither'?


    I don't know. English was never my strong point.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
     
    Richard Heathfield, Jan 15, 2007
    #15
  16. CBFalconer Guest

    santosh wrote:
    > wrote:
    >>
    >>> English was never my strong point.
    >>> --Richard Heathfield in comp.lang.c

    >>
    >> Mine either.

    >
    > Shouldn't this be 'Mine neither'?


    I suggest "Nor mine, neither yours" :)

    --
    Some informative links:
    <http://members.fortunecity.com/nnqweb/> (newusers)
    <http://www.catb.org/~esr/faqs/smart-questions.html>
    <http://www.caliburn.nl/topposting.html>
    <http://www.netmeister.org/news/learn2quote.html>
    <http://cfaj.freeshell.org/google/> (taming google)
     
    CBFalconer, Jan 15, 2007
    #16
  17. In article <>,
    <> wrote:
    >> <> wrote:
    >> >This post is about how to get generic modules in a C environment. The
    >> >aim is to get close to Ada generics. Using C++ is not an option. It
    >> >should all run in a simple C compiler.

    >>
    >> [...]

    >
    >Dave Vandervies wrote:
    >> [...]
    >> Comment #2: What's wrong with a qsort-style interface?

    >
    >It is not close to Ada, and the style only works for functions, not for
    >modules. (?)


    If you want Ada, you know where to find it.


    >I don't like function pointers.


    If you want Java, you know where to find it.

    > Anyway, the hardware we use makes it
    >impossible to use function pointers. It has to do with fixed adresses
    >for variables that would normally be on the stack, and a very small
    >RAM.


    In that case, it might be worth your time to write (or find) a code
    generator that instantiates the generics you need for the types you need
    them for, and feed the output of that to your C compiler.

    Or you could use a C++ compiler and treat it as C-with-templates. If you
    can find one that targets embedded platforms, it can probably even be told
    to generate code as if it were C-with-templates and not full-blown C++.

    Or you could find an Ada compiler and use *real* Ada generics instead
    of trying to fake it in a language where it's a foreign idiom.


    dave

    --
    Dave Vandervies
    Are you sure that Kraft's Pasteurized Process Cheese Food actually spoils?
    I'm not convinced that any self-respecting microbe would be seen near it.
    --Egroeg Ltreahcs in the scary devil monastery
     
    Dave Vandervies, Jan 15, 2007
    #17
  18. user923005 Guest

    I did something like what you want in C-Unleashed's sorting chapter
    (code found here):
    http://users.powernet.co.uk/eton/unleashed/errata/896213nw.zip

    You will see that I use a generic framework (using header files) and
    then resolve to the appropriate type at compile time. You could call
    it a poor man's template.

    It's a lot easier with the appropriate plumbing, though.
     
    user923005, Jan 15, 2007
    #18
  19. Ben Pfaff Guest

    writes:

    > This post is about how to get generic modules in a C environment. The
    > aim is to get close to Ada generics. Using C++ is not an option. It
    > should all run in a simple C compiler.
    >
    > When I think of a generic module, it is something that can be used
    > exactly as it is. The generic H-file and/or C-file, should not have to
    > be edited AT ALL in order to use it. If it has to be changed in just 1
    > line, it could possibly still have great reusability properties, but it
    > is not generic in the sense I mean.


    I recently created a simple module for circular deques that might
    fit your criteria. Here's the header file (there's no .c file).
    I don't know whether it generalizes naturally to more complicated
    data structures, because I've only tried it with this one so
    far. It depends on a few project-specific functions, but I'm
    sure you can fill in the blanks:

    /* PSPP - computes sample statistics.
    Copyright (C) 2007 Free Software Foundation, Inc.

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA. */

    #ifndef LIBPSPP_DEQUE_H
    #define LIBPSPP_DEQUE_H 1

    #include <assert.h>
    #include <stdbool.h>
    #include <stddef.h>

    #include <libpspp/compiler.h>

    #include "xalloc.h"

    /* Declares data and functions for a deque whose elements have
    the given ELEMENT_TYPE. Instances of the deque are declared
    as "struct NAME", and each function that operates on the deque
    has NAME_ as a prefix. */
    #define DEQUE_DECLARE(NAME, ELEMENT_TYPE) \
    /* An instance of the deque. */ \
    struct NAME \
    { \
    size_t capacity; /* Capacity, which must be a power of 2. */ \
    size_t front; /* One past the front of the queue. */ \
    size_t back; /* The back of the queue. */ \
    ELEMENT_TYPE *data; /* Pointer to CAPACITY elements. */ \
    }; \
    \
    /* Initializes DEQUE as an empty deque that can store at least \
    CAPACITY elements. (The actual capacity may be larger and is \
    always a power of 2.) */ \
    static inline void \
    NAME##_init (struct NAME *deque, size_t capacity) \
    { \
    deque->capacity = 1; \
    while (deque->capacity < capacity) \
    deque->capacity *= 2; \
    deque->front = deque->back = 0; \
    deque->data = xnmalloc (deque->capacity, sizeof *deque->data); \
    } \
    \
    /* Destroys DEQUE, which must be empty. */ \
    static inline void \
    NAME##_destroy (struct NAME *deque) \
    { \
    free (deque->data); \
    } \
    \
    /* Returns the number of elements currently in DEQUE. */ \
    static inline size_t \
    NAME##_count (const struct NAME *deque) \
    { \
    return deque->front - deque->back; \
    } \
    \
    /* Returns the maximum number of elements that DEQUE can hold at \
    any time. */ \
    static inline size_t \
    NAME##_capacity (const struct NAME *deque) \
    { \
    return deque->capacity; \
    } \
    \
    /* Returns true if DEQUE is currently empty (contains no \
    elements), false otherwise. */ \
    static inline bool \
    NAME##_is_empty (const struct NAME *deque) \
    { \
    return NAME##_count (deque) == 0; \
    } \
    \
    /* Returns true if DEQUE is currently full (cannot take any more \
    elements), false otherwise. */ \
    static inline bool \
    NAME##_is_full (const struct NAME *deque) \
    { \
    return NAME##_count (deque) >= NAME##_capacity (deque); \
    } \
    \
    /* Returns the element in DEQUE that is OFFSET elements from its \
    front. A value 0 for OFFSET requests the element at the \
    front, a value of 1 the element just behind the front, and so \
    on. OFFSET must be less than the current number of elements \
    in DEQUE. */ \
    static inline ELEMENT_TYPE * \
    NAME##_front (const struct NAME *deque, size_t offset) \
    { \
    assert (NAME##_count (deque) > offset); \
    return &deque->data[(deque->front - offset - 1) & (deque->capacity - 1)]; \
    } \
    \
    /* Returns the element in DEQUE that is OFFSET elements from its \
    back. A value 0 for OFFSET requests the element at the back, \
    a value of 1 the element just ahead of the back, and so on. \
    OFFSET must be less than the current number of elements in \
    DEQUE. */ \
    static inline ELEMENT_TYPE * \
    NAME##_back (const struct NAME *deque, size_t offset) \
    { \
    assert (NAME##_count (deque) > offset); \
    return &deque->data[(deque->back + offset) & (deque->capacity - 1)]; \
    } \
    \
    /* Adds and returns the address of a new element at the front of \
    DEQUE, which must not be full. The caller is responsible for \
    assigning a value to the returned element. */ \
    static inline ELEMENT_TYPE * \
    NAME##_push_front (struct NAME *deque) \
    { \
    assert (!NAME##_is_full (deque)); \
    return &deque->data[deque->front++ & (deque->capacity - 1)]; \
    } \
    \
    /* Adds and returns the address of a new element at the back of \
    DEQUE, which must not be full. The caller is responsible for \
    assigning a value to the returned element. */ \
    static inline ELEMENT_TYPE * \
    NAME##_push_back (struct NAME *deque) \
    { \
    assert (!NAME##_is_full (deque)); \
    return &deque->data[--deque->back & (deque->capacity - 1)]; \
    } \
    \
    /* Pops the front element off DEQUE (which must not be empty) and \
    returns its address. The element may be reused the next time \
    an element is pushed into DEQUE or when DEQUE is expanded. */ \
    static inline ELEMENT_TYPE * \
    NAME##_pop_front (struct NAME *deque) \
    { \
    assert (!NAME##_is_empty (deque)); \
    return &deque->data[--deque->front & (deque->capacity - 1)]; \
    } \
    \
    /* Pops the back element off DEQUE (which must not be empty) and \
    returns its address. The element may be reused the next time \
    an element is pushed into DEQUE or when DEQUE is expanded. */ \
    static inline ELEMENT_TYPE * \
    NAME##_pop_back (struct NAME *deque) \
    { \
    assert (!NAME##_is_empty (deque)); \
    return &deque->data[deque->back++ & (deque->capacity - 1)]; \
    } \
    \
    /* Expands DEQUE, doubling its capacity. */ \
    static inline void \
    NAME##_expand (struct NAME *deque) \
    { \
    struct NAME old_deque = *deque; \
    NAME##_init (deque, deque->capacity * 2); \
    while (!NAME##_is_empty (&old_deque)) \
    *NAME##_push_front (deque) = *NAME##_pop_back (&old_deque); \
    free (old_deque.data); \
    }

    #endif /* libpspp/deque.h */

    --
    "We put [the best] Assembler programmers in a little glass case in the hallway
    near the Exit sign. The sign on the case says, `In case of optimization
    problem, break glass.' Meanwhile, the problem solvers are busy doing their
    work in languages most appropriate to the job at hand." --Richard Riehle
     
    Ben Pfaff, Jan 15, 2007
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Willem Oosthuizen
    Replies:
    1
    Views:
    2,786
    Jonathan Bromley
    Jul 9, 2003
  2. Acciduzzu

    Integers only as generics?

    Acciduzzu, Sep 22, 2003, in forum: VHDL
    Replies:
    4
    Views:
    724
    Allan Herriman
    Sep 23, 2003
  3. valentin tihomirov

    generics in TB

    valentin tihomirov, Dec 17, 2003, in forum: VHDL
    Replies:
    4
    Views:
    593
    valentin tihomirov
    Dec 18, 2003
  4. Juergen Berchtel
    Replies:
    1
    Views:
    5,999
    John C. Bollinger
    May 20, 2005
  5. Soul
    Replies:
    0
    Views:
    524
Loading...

Share This Page