Request for source code review of simple Ising model

Discussion in 'C Programming' started by Udyant Wig, Apr 10, 2014.

  1. Udyant Wig

    Udyant Wig Guest

    | That merely asserts that:
    |
    | In particular, it's not uncommon for the rand funciton to produce
    | alternately even and odd numbers, such that if you repeatedly
    | compute rand % 2, you'll get the decidedly non-random sequence 0,
    | 1, 0, 1, 0, 1, 0, 1... .
    |
    | I'm looking for concrete examples of real-world implementations that
    | behave this way.

    As Ike Naar writes in the article with
    Message-ID: <>:
    | Here it prints
    |
    | 0101010101010101010101010101010101010101010101010101010101010101
    |
    | The implementation is gcc version 4.5.3 (NetBSD nb2 20110806).

    This is the implementation of rand() in NetBSD's libc:

    /* $NetBSD: rand.c,v 1.12 2012/06/25 22:32:45 abs Exp $ */

    /*-
    * Copyright (c) 1990, 1993
    * The Regents of the University of California. All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the distribution.
    * 3. Neither the name of the University nor the names of its contributors
    * may be used to endorse or promote products derived from this software
    * without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    */

    #include <sys/cdefs.h>
    #if defined(LIBC_SCCS) && !defined(lint)
    #if 0
    static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93";
    #else
    __RCSID("$NetBSD: rand.c,v 1.12 2012/06/25 22:32:45 abs Exp $");
    #endif
    #endif /* LIBC_SCCS and not lint */

    #include <sys/types.h>
    #include <stdlib.h>

    static u_long next = 1;

    int
    rand(void)
    {
    /* LINTED integer overflow */
    return (int)((next = next * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
    }

    void
    srand(u_int seed)
    {
    next = seed;
    }
     
    Udyant Wig, Apr 19, 2014
    #61
    1. Advertisements

  2. Udyant Wig

    Udyant Wig Guest

    | For instance, your code uses
    |
    | double random_value = (double) (rand () % 100) / 100.0;
    |
    | It is guaranteed that 0 <= random_value && random_value < 1.0, and
    | (after allowing for floating point round-off), random_value will be an
    | integer multiple of 0.01. However, it will not produce all 100
    | different possible values with equal probability (not even if rand()
    | were an ideal random number generator). See if you can figure out why.
    | Hint: if RAND_MAX were 32799, it would work.

    Qualitatively, if RAND_MAX is 32767, then rand () % 100 will produce
    values between 0 and 67 with a higher probability than it will those
    between 68 and 99.
     
    Udyant Wig, Apr 19, 2014
    #62
    1. Advertisements

  3. Udyant Wig

    Udyant Wig Guest

    |> The two outputs are equal. Independent confirmations by Emacs Lisp,
    |>
    |> (string-equal
    |> "1011110011010110000010110001111000111010111101001010100100011101"
    |> "1011110011010110000010110001111000111010111101001010100100011101")
    |> => t
    |>
    |> and their MD5 sums,
    |>
    |> $ md5sum # Keith Thompson's output
    |> 1011110011010110000010110001111000111010111101001010100100011101
    |> 89e91cff9eefca6a24afaee2809c0859 -
    |>
    |> $ md5sum # Udyant Wig's output
    |> 1011110011010110000010110001111000111010111101001010100100011101
    |> 89e91cff9eefca6a24afaee2809c0859 -
    |>
    |> verify this.
    |>
    |
    | Serious Q : are you taking the piss?

    I went overboard with the confirmations. It was _not_ my intention to
    abuse trust at all. I apologize if that came across as mocking.
     
    Udyant Wig, Apr 19, 2014
    #63
  4. (snip)
    And how many calls will it take for the difference to be
    statistically significant?

    -- glen
     
    glen herrmannsfeldt, Apr 19, 2014
    #64
  5. Udyant Wig

    Stefan Ram Guest

    When you have used rand()%100 in a program or a library and
    then release this to third parties, how do you know or
    control how often this program is being started or the
    library function is being called?
     
    Stefan Ram, Apr 19, 2014
    #65
  6. Fascinating. So there *are* modern implementations that have this
    problem.

    The relevant implementation is the C standard library, not the compiler.
    BSD has its own C standard library implementation. I wonder if Mac OSX
    (which is based on BSD) has this problem.

    The man page
    http://netbsd.gw.com/cgi-bin/man-cgi?rand+3+NetBSD-current
    doesn't mention this, apart from the NAME section:

    rand, srand, rand_r -- bad random number generator
     
    Keith Thompson, Apr 19, 2014
    #66
  7. Udyant Wig

    Ian Collins Guest

    It doesn't.

    1110000011010011110011110110011001011111101011010111000000010010
    But it does have the same man page!
     
    Ian Collins, Apr 19, 2014
    #67
  8. Udyant Wig

    Stefan Ram Guest

    IIRC, one version of the C standard contained a simplistic
    example of how rand() might be implemented, and many
    implementation manufacturers seemed to have copied this.

    I am using rand() in my courses, because rand() is a simple
    example of a function that can be called before function-call
    arguments are introduced, and I therefore hope that rand()
    will not be removed from the standard library of C.

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3841.pdf
     
    Stefan Ram, Apr 19, 2014
    #68
  9. Udyant Wig

    Stefan Ram Guest

    There might be other factors that hide those relatively
    small differences.

    This program shows the relative deviations in per thousand
    when using »rand() %« in one single case:

    #include <stdio.h> /* printf */
    #include <stdlib.h> /* RAND_MAX, rand() */
    #define N 5e6
    #define COVER 10
    int a[ COVER + 2 ];
    int main( void )
    { for( int i = 0; i < N; ++i )++a[ 1 + rand() % COVER ];
    for( int i = 0; i < COVER; ++i )
    printf( "%d:%+f\n", i, 1000*( a[ i + 1 ]/( N / COVER )- 1 )); }

    0:+0.396000
    1:-1.370000
    2:+0.070000
    3:-0.572000
    4:-0.154000
    5:-1.236000
    6:+0.004000
    7:+4.234000
    8:-0.470000
    9:-0.902000

    I.e., the number 7 is more frequent by a factor of about 1.004234
    than in the case of equi partition.

    Now, let's try this with the Mersenne Twister 19937 generator from C++:

    #include <stdio.h> /* printf */
    #include <stdlib.h> /* RAND_MAX, rand() */
    #include <random> /* ::std::mt19937, ::std::uniform_int_distribution */
    #define N 5e6
    #define COVER 10
    int a[ COVER + 2 ];
    int main( void )
    { ::std::mt19937 mt19937;
    ::std::uniform_int_distribution< int >distribution{ 0, COVER - 1 };
    auto const dice =[ & ]()-> int{ return distribution( mt19937 ); };
    for( int i = 0; i < N; ++i )++a[ 1 + dice() ];
    for( int i = 0; i < COVER; ++i )
    printf( "%d:%+f\n", i, 1000*( a[ i + 1 ]/( N / COVER )- 1 )); }

    0:-0.208000
    1:+0.524000
    2:-0.854000
    3:+0.164000
    4:-0.066000
    5:-2.100000
    6:+1.604000
    7:+0.078000
    8:+1.804000
    9:-0.946000

    So, the distribution is not so much worse when using »rand()%«
    in the special case of my above test and the C implementation used.
     
    Stefan Ram, Apr 20, 2014
    #69
  10. The 1990, 1999, and 2011 ISO C standards all include a non-normative
    sample implementation of rand() (one that assume RAND_MAX==32767) -- but
    it doesn't suffer from the problem that the low-order bits consistently
    alternate between 0 and 1.
    The link is to proposal to discourage the use of rand() in C++14. I
    don't think there's much chance rand() will be removed from C any time
    soon. If it were removed, there would have to be a better replacement
    for it. There's no shortage of better PRNGs, but I expect that deciding
    which one (if any) to mandate would be difficult.

    I suppose that a future standard could add a new PRNG that can be seeded
    with more information than the existing srand(), which only takes a
    single unsigned int.

    One requirement that rand() must satisfy is that it always yields the
    same sequence of numbers for a given seed. That might not be compatible
    with the requirements of cryptography, for example, unless you also
    provide way to feed it a high-quality seed.
     
    Keith Thompson, Apr 20, 2014
    #70
  11. I've grabbed a copy of source code for the NetBSD libc implementation of
    rand() and run the same test on it on some of my own systems (64-bit
    Linux Mint 14, 32-bit Ubuntu 12.10ish, and Cygwin on Windows 7), and I
    *didn't* see alternating 0 and 1 low-order bits. I even examined all
    available versions from the NetBSD CVS repository (the history goes back
    to 1993), and I see no differences in the available history that would
    explain this behavior. Obviously I'm missing something.

    Ike: What is "NetBSD nb2 20110806"? The latest release of NetBSD is
    6.1.4; how does it relate to that?

    I've set up a GitHub project for this at
    https://github.com/Keith-S-Thompson/crude_rand_test
     
    Keith Thompson, Apr 20, 2014
    #71
  12. Udyant Wig

    Udyant Wig Guest

    -berlin.de (Stefan Ram) writes:
    | This program shows the relative deviations in per thousand
    | when using »rand() %« in one single case:
    |
    | #include <stdio.h> /* printf */
    | #include <stdlib.h> /* RAND_MAX, rand() */
    | #define N 5e6
    | #define COVER 10
    | int a[ COVER + 2 ];
    | int main( void )
    | { for( int i = 0; i < N; ++i )++a[ 1 + rand() % COVER ];
    | for( int i = 0; i < COVER; ++i )
    | printf( "%d:%+f\n", i, 1000*( a[ i + 1 ]/( N / COVER )- 1 )); }
    |
    | 0:+0.396000
    | 1:-1.370000
    | 2:+0.070000
    | 3:-0.572000
    | 4:-0.154000
    | 5:-1.236000
    | 6:+0.004000
    | 7:+4.234000
    | 8:-0.470000
    | 9:-0.902000

    I get this:

    0:-2.388000
    1:-0.510000
    2:-1.028000
    3:-1.276000
    4:+3.250000
    5:-0.390000
    6:-1.664000
    7:+1.018000
    8:+2.154000
    9:+0.834000

    There is a greater number of 4's and 8's.
     
    Udyant Wig, Apr 20, 2014
    #72
  13. Udyant Wig

    Udyant Wig Guest

    | Keith Thompson wrote:
    |> The relevant implementation is the C standard library, not the
    |> compiler. BSD has its own C standard library implementation. I
    |> wonder if Mac OSX (which is based on BSD) has this problem.
    |
    | It doesn't.
    |
    | 1110000011010011110011110110011001011111101011010111000000010010

    It uses the same rand() as FreeBSD:

    http://www.opensource.apple.com/source/Libc/Libc-997.1.1/stdlib/FreeBSD/rand.c
     
    Udyant Wig, Apr 20, 2014
    #73
  14. Udyant Wig

    Udyant Wig Guest

    I have created a repository for this program at Bitbucket. It
    incorporates James Kuyper's suggestion to initialize each cell of the
    lattice with the bits of each number produced by rand(), rather than
    calling rand() for each cell and then extracting just one bit.

    https://bitbucket.org/udyant/bitsing-bits-ising-model

    Udyant Wig
     
    Udyant Wig, Apr 20, 2014
    #74
  15. Udyant Wig

    Ike Naar Guest

    $ uname -a
    NetBSD iceland 6.1_STABLE NetBSD 6.1_STABLE (SDF6.amd64) #0: Tue Nov 26 12:49:14 UTC 2013 root@bjork:/spare/netbsd/src/sys/arch/amd64/compile/SDF6.amd64 amd64
     
    Ike Naar, Apr 20, 2014
    #75
  16. Udyant Wig

    James Kuyper Guest

    A relatively tiny number, for any program involving serious number
    crunching. It's a difference of 1/327, which is fairly large number for
    certain purposes, and a completely negligible one for other purposes -
    the key point is making sure you know which category your particular
    case involves.
     
    James Kuyper, Apr 20, 2014
    #76
  17. Udyant Wig

    Udyant Wig Guest

    | James Kuyper <| writes:
    | | And that brings to mind another issue. Once you're sure that your
    | | program is working, and you've reached the point where it's
    | | reasonable to worry about performance, you might consider an
    | | alternative data storage strategy. You're using one byte to store
    | | one cell representing a spin 1/2 object: it therefore has only two
    | | quantized orientations, up and down, so you're storing only one bit
    | | of information for that cell. It might be better to use, for
    | | example, a 32-bit integer to store the values of 32 consecutive
    | | cells. Not only will this use up a lot less memory, but with (quite)
    | | a bit of ingenuity, you can use bit-wise operations to handle all 32
    | | cells at the same time, for a naive speed-up by a factor of 32. In
    | | practice, the speed up will actually be less than that, but should
    | | still be substantial. On the other hand, if you implement this idea
    | | your code will be a lot more complicated, and much harder to
    | | understand. You'll have to decide whether that's a acceptable cost
    | | for the increased processing speed and decreased memory
    | | requirements.
    |
    | This would be another rewrite of the program, as much of the existing
    | source would have to be modified for this data representation.
    |
    | It should be worth looking into, because, as I said elsewhere, a
    | given run of a 10x10 lattice can take upwards of three hours and not
    | complete, while a 6x6 one finishes in mere minutes.

    I found this to be somewhat difficult initially. After thinking and
    writing, and some more thinking and rewriting, I developed the appended
    source. Though I have not yet found out a way to handle 32 bits at
    once, I did manage to use as many 32-bit integers as are required to
    house dimension * dimension bits. So, a single int32_t can contain
    upto 5x5 bits, while two can contain upto 8x8, etc.

    Testing showed that this is faster than the earlier version wherein I
    used the integers as mere sources of bits for the lattice.

    The general structure remains the same.


    /* common.h begins */

    #ifndef COMMON_H
    #define COMMON_H

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <math.h>
    #include <stdbool.h>
    #include <time.h>
    #include <ctype.h>
    #include <stdint.h>

    #endif

    /* common.h ends */


    /* utilities.h begins */

    #ifndef UTILITIES_H
    #define UTILITIES_H

    #include "common.h"

    bool is_all_zeroes (char *string);
    bool is_positive_integer (char *string);
    int how_many (const char *s, int c);
    char *copy_substring (char *substring, const char *string, size_t start, size_t end);
    int minimum_multiple_32 (int n);

    #endif

    /* utilities.h ends */


    /* utilities.c begins */

    #include "utilities.h"

    bool is_all_zeroes (char *string)
    {
    return string [strspn (string, "0")] == '\0';
    }

    bool is_positive_integer (char *string)
    {
    char *sp;

    for (sp = string; *sp != '\0'; sp++) {
    if (!isdigit (*sp)) {
    return false;
    }
    }

    return !is_all_zeroes (string);
    }

    /* From /C: A Reference Manual/, 5th ed., by Harbison and Steele
    * page 352
    */
    int how_many (const char *s, int c)
    {
    int n = 0;
    if (c == 0) return 0;
    while (s) {
    s = strchr (s, c);
    if (s) n++, s++;
    }
    return n;
    }

    char *copy_substring (char *substring, const char *string, size_t start, size_t end)
    {
    size_t length = end - start + 1;

    errno = 0;
    substring = malloc (1 + length);
    if (substring == NULL) {
    fprintf (stderr, "copy_substring: %s\n", strerror (errno));
    exit (1);
    }

    memset (substring, 0, 1 + length);
    strncpy (substring, string + start, length - 1);
    substring [length] = '\0';

    return substring;
    }

    int minimum_multiple_32 (int n)
    {
    int mm32 = n >> 5;
    if (n % 32 != 0) {
    mm32++;
    }
    return mm32;
    }

    /* utilities.c ends */


    /* bitsing.h begins */

    #ifndef BITSING_H
    #define BITSING_H

    /* 32-bit integer bit source that doubles as lattice */
    int32_t *allocate_lattice (size_t size);
    void initialize_lattice (int32_t *lattice);
    void print_lattice (int32_t *lattice);

    /* Energies vector */
    int *allocate_energies (size_t size);
    void initialize_energies (int *energies);

    /* Core */
    int check_and_add_neighbor (int32_t *lattice, int32_t cell, int col, int row);
    void iterate (int32_t *lattice, int *energies);

    /* Miscellaneous */
    int count_ones (int32_t *lattice);
    void print_iteration (int32_t *lattice, const char *format_string, int count);

    /* Error checking */
    void minority_error (void);
    void beta_error (void);
    void dimension_error (void);

    #endif

    /* bitsing.h ends */


    /* bitsing.c begins */

    #include "common.h"
    #include "bitsing.h"
    #include "utilities.h"

    #define INTSRC_BITS 32

    static int dimension = 3;
    static double beta = 0.5;
    static int minority_size = 1;

    /* 32-bit integer bit source that doubles as lattice */
    int32_t *allocate_lattice (size_t size)
    {
    int32_t *lattice;
    lattice = malloc (size);
    if (lattice == NULL) {
    fprintf (stderr, "allocate_lattice: %s\n", strerror (errno));
    exit (2);
    }
    return lattice;
    }

    void initialize_lattice (int32_t *lattice)
    {
    int int_count = minimum_multiple_32 (dimension * dimension);
    int32_t *ip = lattice, *end = ip + int_count;
    while (ip < end) {
    *ip = (int32_t) (rand () % RAND_MAX);
    ip++;
    }
    }

    void print_lattice (int32_t *lattice)
    {
    int row, col;
    int position;

    for (col = 0; col < dimension; col++) {
    for (row = 0; row < dimension; row++) {
    position = col * dimension + row;
    printf ("%d", (lattice [position / INTSRC_BITS] >> (position % INTSRC_BITS)) & 1);
    }
    putchar ('\n');
    }
    }


    /* Energies vector */
    int *allocate_energies (size_t size)
    {
    int *energies;
    energies = malloc (size);
    if (energies == NULL) {
    fprintf (stderr, "allocate_energies: %s\n", strerror (errno));
    exit (2);
    }
    return energies;
    }

    void initialize_energies (int *energies)
    {
    int *ep = energies, *end = ep + dimension * dimension;
    while (ep < end) {
    *ep = 0;
    ep++;
    }
    }


    /* Core */
    int check_and_add_neighbor (int32_t *lattice, int cell_bit, int col, int row)
    {
    int neighbor_bit;
    int position;
    if (0 <= col && 0 <= row && col < dimension && row < dimension) {
    position = col * dimension + row;
    neighbor_bit = (lattice [position / INTSRC_BITS] >> (position % INTSRC_BITS)) & 1;
    return cell_bit ^ neighbor_bit;
    }
    return 0;
    }

    void iterate (int32_t *lattice, int *energies)
    {
    int rrow, rcol;
    int position;
    int rcell_bit, ccell_bit;
    int old_energy;
    int new_energy;
    int delta;

    rrow = rand () % dimension;
    rcol = rand () % dimension;
    position = rcol * dimension + rrow;
    rcell_bit = (lattice [position / INTSRC_BITS] >> (position % INTSRC_BITS)) & 1;
    ccell_bit = rcell_bit ^ 1; /* comlemented cell */
    old_energy = energies [position];

    new_energy = check_and_add_neighbor (lattice, ccell_bit, rrow - 1, rcol);
    new_energy = check_and_add_neighbor (lattice, ccell_bit, rrow + 1, rcol);
    new_energy = check_and_add_neighbor (lattice, ccell_bit, rrow, rcol - 1);
    new_energy = check_and_add_neighbor (lattice, ccell_bit, rrow, rcol + 1);

    delta = new_energy - old_energy;
    if (delta < 0) {
    lattice [position / INTSRC_BITS] ^= (1 << (position % INTSRC_BITS));
    energies [position] = new_energy;
    }
    else {
    double ising_window = exp (-(beta * delta));
    double random_value = (double) (rand () % 100) / 100.0;

    if (random_value < ising_window) {
    lattice [position / INTSRC_BITS] ^= (1 << (position % INTSRC_BITS));
    energies [position] = new_energy;
    }
    }
    }


    /* Miscellaneous */
    int count_ones (int32_t *lattice)
    {
    int count = 0;
    int int_count = minimum_multiple_32 (dimension * dimension);
    int32_t *ip = lattice, *end = ip + int_count;
    int field;
    int i = 0;

    while (ip < end) {
    for (field = *ip; field; field >>= 1) {
    if (i == dimension * dimension) {
    return count;
    }
    count += field & 1;
    i++;
    }
    ip++;
    }

    return count;
    }

    static const char initial_format [] = \
    "Initial configuration %6d\n----------------------------\n";
    static const char iteration_format [] = \
    "Iteration %6d\n----------------\n";
    static const char final_format [] = \
    "Final configuration %6d\n--------------------------\n";

    void print_iteration (int32_t *lattice, const char *format_string, int count)
    {
    putchar ('\n');
    printf (format_string, count);
    print_lattice (lattice);
    }


    /* Error checking */
    void minority_error (void)
    {
    exit (2);
    }

    void beta_error (void)
    {
    exit (2);
    }

    void dimension_error (void)
    {
    exit (2);
    }


    /* Return codes:
    * 0 -- success
    * 1 -- memory allocation failure
    * 2 -- invalid command line argument
    */
    int main (int argc, char *argv [])
    {
    if (argc > 3) {
    if (is_positive_integer (argv [3]) || is_all_zeroes (argv [3])) {
    minority_size = atoi (argv [3]);
    }
    else {
    minority_error ();
    }

    if (minority_size < 0) {
    minority_size = 0;
    }
    else if (minority_size > dimension * dimension) {
    minority_size = dimension * dimension;
    }
    else if (minority_size > (dimension * dimension) / 2) {
    minority_size = (dimension * dimension) - minority_size;
    }
    }
    if (argc > 2) {
    char *beta_string = argv [2];
    size_t length = strlen (beta_string);

    if (how_many (beta_string, '.') == 1) {
    size_t position_decimal = strcspn (beta_string, ".");
    char *integral_part = NULL;
    char *fractional_part = NULL;

    if (position_decimal == 0) {
    beta_error ();
    }
    if (position_decimal == strlen (beta_string) - 1) {
    beta_error ();
    }

    integral_part = copy_substring (integral_part, \
    beta_string, \
    0, \
    position_decimal - 1);
    if (is_positive_integer (integral_part) || \
    is_all_zeroes (integral_part)) {
    fractional_part = copy_substring (fractional_part, \
    beta_string, \
    position_decimal + 1, \
    length - 1);
    if (is_positive_integer (fractional_part) || \
    is_all_zeroes (fractional_part)) {
    beta = atof (argv [2]);
    }
    else {
    beta_error ();
    }

    free (fractional_part);
    }
    else {
    beta_error ();
    }

    free (integral_part);
    }
    else {
    beta_error ();
    }
    }
    if (argc > 1) {
    if (is_positive_integer (argv [1]))
    dimension = atoi (argv [1]);
    else {
    dimension_error ();
    }
    }

    srand (time (0));

    int32_t *lattice;
    lattice = allocate_lattice (minimum_multiple_32 (dimension * dimension) \
    * sizeof *lattice);
    initialize_lattice (lattice);

    int *energies;
    energies = allocate_energies (dimension * dimension * sizeof *energies);
    initialize_energies (energies);

    print_iteration (lattice, initial_format, 0);

    long count = 1;
    while (true) {
    iterate (lattice, energies);

    int ones_count = count_ones (lattice);
    if ((ones_count == minority_size) || \
    ((dimension * dimension - ones_count) == minority_size)) {
    break;
    }

    print_iteration (lattice, iteration_format, count++);
    }

    print_iteration (lattice, final_format, count);
    free (energies);
    free (lattice);

    exit (0);
    }

    /* bitsing.c ends */
     
    Udyant Wig, Apr 20, 2014
    #77
  18. I see you're still not casting the argument to isdigit(). That causes
    undefined behavior if plain char is signed and your string contains a
    character with a negative value (which probably represents a character
    greater than 127).

    [...]
     
    Keith Thompson, Apr 20, 2014
    #78
  19. Udyant Wig

    Ike Naar Guest

    Testing the low-order bits of the result of rand() from current implementation
    0101010101010101010101010101010101010101010101010101010101010101
    Low order bits alternate 0 and 1 (bad)

    Testing the low-order bits of the result of rand() from ISO C sample implementation
    0101010101010101010101010101010101010101010101010101010101010101
    Low order bits alternate 0 and 1 (bad)

    Testing the low-order bits of the result of rand() from NetBSD
    0101010101010101010101010101010101010101010101010101010101010101
    Low order bits alternate 0 and 1 (bad)
     
    Ike Naar, Apr 20, 2014
    #79
  20. Udyant Wig

    jacob navia Guest

    Le 19/04/2014 23:39, Keith Thompson a écrit :
    No, not at first sight anyway No repeating pattern as far as I see:

    1110000011010011110011110110011001011111101011010111000000010010

    My mac is like this:

    uname -a
    Darwin macpro.local 13.1.0 Darwin Kernel Version 13.1.0: Thu Jan 16
    19:40:37 PST 2014; root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64

    It is a nice machine, the best Unix I have ever used.
     
    jacob navia, Apr 20, 2014
    #80
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.