Added files in src/math
[pspp] / src / casefile.c
index f7d171f766be4402fdd9a104b8ca827ae7b59023..8fe0740371aee2eab107119a46789e99ede08a64 100644 (file)
 #include "alloc.h"
 #include "case.h"
 #include "error.h"
 #include "alloc.h"
 #include "case.h"
 #include "error.h"
+#include "full-read.h"
+#include "full-write.h"
 #include "misc.h"
 #include "mkfile.h"
 #include "settings.h"
 #include "var.h"
 
 #include "misc.h"
 #include "mkfile.h"
 #include "settings.h"
 #include "var.h"
 
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
 #define IO_BUF_SIZE (8192 / sizeof (union value))
 
 /* A casefile represents a sequentially accessible stream of
 #define IO_BUF_SIZE (8192 / sizeof (union value))
 
 /* A casefile represents a sequentially accessible stream of
           independent position in the casefile.
 
           Casereaders may only move forward.  They cannot move
           independent position in the casefile.
 
           Casereaders may only move forward.  They cannot move
-          backward to arbitrary records or seek randomly.  (In the
-          future, the concept of a "casemark" will be introduced
-          to allow a limited form of backward seek, but this has
-          not yet been implemented.)
-
-          Cloning casereaders is possible, but no one has had a
-          need for it yet, so it is not implemented.
+          backward to arbitrary records or seek randomly.
+          Cloning casereaders is possible, but it is not yet
+          implemented.
 
           Use casefile_get_reader() to create a casereader for
 
           Use casefile_get_reader() to create a casereader for
-          use in phase 2.  This also transitions from phase 2 to
-          phase 3.  Calling casefile_mode_reader() makes the same
+          use in phase 2.  This also transitions from phase 1 to
+          phase 2.  Calling casefile_mode_reader() makes the same
           transition, without creating a casereader.
 
           Use casereader_read(), casereader_read_xfer(), or
           transition, without creating a casereader.
 
           Use casereader_read(), casereader_read_xfer(), or
@@ -83,9 +84,8 @@
           also read with casereaders in this phase, but the
           ability to create new casereaders is curtailed.
 
           also read with casereaders in this phase, but the
           ability to create new casereaders is curtailed.
 
-          In this phase, casereaders could still be cloned, and
-          casemarks could still be used to seek backward (given
-          that we eventually implement these functionalities).
+          In this phase, casereaders could still be cloned (once
+          we eventually implement cloning).
 
           To transition from phase 1 or 2 to phase 3 and create a
           casereader, call casefile_get_destructive_reader().
 
           To transition from phase 1 or 2 to phase 3 and create a
           casereader, call casefile_get_destructive_reader().
@@ -96,8 +96,8 @@
           more casereaders may be created with
           casefile_get_reader() or
           casefile_get_destructive_reader().  (If cloning of
           more casereaders may be created with
           casefile_get_reader() or
           casefile_get_destructive_reader().  (If cloning of
-          casereaders or casemarks were implemented, they would
-          still be possible.)
+          casereaders were implemented, it would still be
+          possible.)
 
           The purpose of the limitations applied to casereaders
           in phase 3 is to allow in-memory casefiles to fully
 
           The purpose of the limitations applied to casereaders
           in phase 3 is to allow in-memory casefiles to fully
@@ -178,8 +178,6 @@ static void fill_buffer (struct casereader *reader);
 
 static int safe_open (const char *filename, int flags);
 static int safe_close (int fd);
 
 static int safe_open (const char *filename, int flags);
 static int safe_close (int fd);
-static int full_read (int fd, void *buffer, size_t size);
-static int full_write (int fd, const void *buffer, size_t size);
 
 /* Creates and returns a casefile to store cases of VALUE_CNT
    `union value's each. */
 
 /* Creates and returns a casefile to store cases of VALUE_CNT
    `union value's each. */
@@ -333,7 +331,7 @@ casefile_append (struct casefile *cf, const struct ccase *c)
   /* Try memory first. */
   if (cf->storage == MEMORY) 
     {
   /* Try memory first. */
   if (cf->storage == MEMORY) 
     {
-      if (case_bytes < get_max_workspace ())
+      if (case_bytes < get_workspace ())
         {
           size_t block_idx = cf->case_cnt / CASES_PER_BLOCK;
           size_t case_idx = cf->case_cnt % CASES_PER_BLOCK;
         {
           size_t block_idx = cf->case_cnt / CASES_PER_BLOCK;
           size_t case_idx = cf->case_cnt % CASES_PER_BLOCK;
@@ -346,12 +344,12 @@ casefile_append (struct casefile *cf, const struct ccase *c)
               if ((block_idx & (block_idx - 1)) == 0) 
                 {
                   size_t block_cap = block_idx == 0 ? 1 : block_idx * 2;
               if ((block_idx & (block_idx - 1)) == 0) 
                 {
                   size_t block_cap = block_idx == 0 ? 1 : block_idx * 2;
-                  cf->cases = xrealloc (cf->cases,
-                                        sizeof *cf->cases * block_cap);
+                  cf->cases = xnrealloc (cf->cases,
+                                         block_cap, sizeof *cf->cases);
                 }
 
                 }
 
-              cf->cases[block_idx] = xmalloc (sizeof **cf->cases
-                                              * CASES_PER_BLOCK);
+              cf->cases[block_idx] = xnmalloc (CASES_PER_BLOCK,
+                                               sizeof **cf->cases);
             }
 
           case_move (&cf->cases[block_idx][case_idx], &new_case);
             }
 
           case_move (&cf->cases[block_idx][case_idx], &new_case);
@@ -426,7 +424,7 @@ casefile_to_disk (const struct casefile *cf_)
       cf->storage = DISK;
       if (!make_temp_file (&cf->fd, &cf->filename))
         err_failure ();
       cf->storage = DISK;
       if (!make_temp_file (&cf->fd, &cf->filename))
         err_failure ();
-      cf->buffer = xmalloc (cf->buffer_size * sizeof *cf->buffer);
+      cf->buffer = xnmalloc (cf->buffer_size, sizeof *cf->buffer);
       memset (cf->buffer, 0, cf->buffer_size * sizeof *cf->buffer);
 
       case_bytes -= cf->case_cnt * cf->case_acct_size;
       memset (cf->buffer, 0, cf->buffer_size * sizeof *cf->buffer);
 
       case_bytes -= cf->case_cnt * cf->case_acct_size;
@@ -551,7 +549,7 @@ reader_open_file (struct casereader *reader)
     }
   else 
     {
     }
   else 
     {
-      reader->buffer = xmalloc (cf->buffer_size * sizeof *cf->buffer);
+      reader->buffer = xnmalloc (cf->buffer_size, sizeof *cf->buffer);
       memset (reader->buffer, 0, cf->buffer_size * sizeof *cf->buffer); 
     }
 
       memset (reader->buffer, 0, cf->buffer_size * sizeof *cf->buffer); 
     }
 
@@ -732,49 +730,6 @@ static int safe_close (int fd)
   return retval;
 }
 
   return retval;
 }
 
-/* Calls read(), passing FD, BUFFER, and SIZE, repeating as
-   necessary to deal with interrupted calls. */
-static int
-full_read (int fd, void *buffer_, size_t size) 
-{
-  char *buffer = buffer_;
-  size_t bytes_read = 0;
-  
-  while (bytes_read < size)
-    {
-      int retval = read (fd, buffer + bytes_read, size - bytes_read);
-      if (retval > 0) 
-        bytes_read += retval; 
-      else if (retval == 0) 
-        return bytes_read;
-      else if (errno != EINTR)
-        return -1;
-    }
-
-  return bytes_read;
-}
-
-/* Calls write(), passing FD, BUFFER, and SIZE, repeating as
-   necessary to deal with interrupted calls. */
-static int
-full_write (int fd, const void *buffer_, size_t size) 
-{
-  const char *buffer = buffer_;
-  size_t bytes_written = 0;
-  
-  while (bytes_written < size)
-    {
-      int retval = write (fd, buffer + bytes_written, size - bytes_written);
-      if (retval >= 0) 
-        bytes_written += retval; 
-      else if (errno != EINTR)
-        return -1;
-    }
-
-  return bytes_written;
-}
-
-
 /* Registers our exit handler with atexit() if it has not already
    been registered. */
 static void
 /* Registers our exit handler with atexit() if it has not already
    been registered. */
 static void
@@ -798,194 +753,3 @@ exit_handler (void)
   while (casefiles != NULL)
     casefile_destroy (casefiles);
 }
   while (casefiles != NULL)
     casefile_destroy (casefiles);
 }
-\f
-#include <gsl/gsl_rng.h>
-#include <stdarg.h>
-#include "command.h"
-#include "lexer.h"
-
-static void test_casefile (int pattern, size_t value_cnt, size_t case_cnt);
-static void get_random_case (struct ccase *, size_t value_cnt,
-                             size_t case_idx);
-static void write_random_case (struct casefile *cf, size_t case_idx);
-static void read_and_verify_random_case (struct casefile *cf,
-                                         struct casereader *reader,
-                                         size_t case_idx);
-static void fail_test (const char *message, ...);
-
-int
-cmd_debug_casefile (void) 
-{
-  static const size_t sizes[] =
-    {
-      1, 2, 3, 4, 5, 6, 7, 14, 15, 16, 17, 31, 55, 73,
-      100, 137, 257, 521, 1031, 2053
-    };
-  int size_max;
-  int case_max;
-  int pattern;
-
-  size_max = sizeof sizes / sizeof *sizes;
-  if (lex_match_id ("SMALL")) 
-    {
-      size_max -= 4;
-      case_max = 511; 
-    }
-  else
-    case_max = 4095;
-  if (token != '.')
-    return lex_end_of_command ();
-    
-  for (pattern = 0; pattern < 6; pattern++) 
-    {
-      const size_t *size;
-
-      for (size = sizes; size < sizes + size_max; size++) 
-        {
-          size_t case_cnt;
-
-          for (case_cnt = 0; case_cnt <= case_max;
-               case_cnt = (case_cnt * 2) + 1)
-            test_casefile (pattern, *size, case_cnt);
-        }
-    }
-  printf ("Casefile tests succeeded.\n");
-  return CMD_SUCCESS;
-}
-
-static void
-test_casefile (int pattern, size_t value_cnt, size_t case_cnt) 
-{
-  struct casefile *cf;
-  struct casereader *r1, *r2;
-  struct ccase c;
-  gsl_rng *rng;
-  size_t i, j;
-
-  rng = gsl_rng_alloc (gsl_rng_mt19937);
-  cf = casefile_create (value_cnt);
-  if (pattern == 5)
-    casefile_to_disk (cf);
-  for (i = 0; i < case_cnt; i++)
-    write_random_case (cf, i);
-  if (pattern == 5)
-    casefile_sleep (cf);
-  r1 = casefile_get_reader (cf);
-  r2 = casefile_get_reader (cf);
-  switch (pattern) 
-    {
-    case 0:
-    case 5:
-      for (i = 0; i < case_cnt; i++) 
-        {
-          read_and_verify_random_case (cf, r1, i);
-          read_and_verify_random_case (cf, r2, i);
-        } 
-      break;
-    case 1:
-      for (i = 0; i < case_cnt; i++)
-        read_and_verify_random_case (cf, r1, i);
-      for (i = 0; i < case_cnt; i++) 
-        read_and_verify_random_case (cf, r2, i);
-      break;
-    case 2:
-    case 3:
-    case 4:
-      for (i = j = 0; i < case_cnt; i++) 
-        {
-          read_and_verify_random_case (cf, r1, i);
-          if (gsl_rng_get (rng) % pattern == 0) 
-            read_and_verify_random_case (cf, r2, j++); 
-          if (i == case_cnt / 2)
-            casefile_to_disk (cf);
-        }
-      for (; j < case_cnt; j++) 
-        read_and_verify_random_case (cf, r2, j);
-      break;
-    }
-  if (casereader_read (r1, &c))
-    fail_test ("Casereader 1 not at end of file.");
-  if (casereader_read (r2, &c))
-    fail_test ("Casereader 2 not at end of file.");
-  if (pattern != 1)
-    casereader_destroy (r1);
-  if (pattern != 2)
-    casereader_destroy (r2);
-  if (pattern > 2) 
-    {
-      r1 = casefile_get_destructive_reader (cf);
-      for (i = 0; i < case_cnt; i++) 
-        {
-          struct ccase read_case, expected_case;
-          
-          get_random_case (&expected_case, value_cnt, i);
-          if (!casereader_read_xfer (r1, &read_case)) 
-            fail_test ("Premature end of casefile.");
-          for (j = 0; j < value_cnt; j++) 
-            {
-              double a = case_num (&read_case, j);
-              double b = case_num (&expected_case, j);
-              if (a != b)
-                fail_test ("Case %lu fails comparison.", (unsigned long) i); 
-            }
-          case_destroy (&expected_case);
-          case_destroy (&read_case);
-        }
-      casereader_destroy (r1);
-    }
-  casefile_destroy (cf);
-  gsl_rng_free (rng);
-}
-
-static void
-get_random_case (struct ccase *c, size_t value_cnt, size_t case_idx) 
-{
-  int i;
-  case_create (c, value_cnt);
-  for (i = 0; i < value_cnt; i++)
-    case_data_rw (c, i)->f = case_idx % 257 + i;
-}
-
-static void
-write_random_case (struct casefile *cf, size_t case_idx) 
-{
-  struct ccase c;
-  get_random_case (&c, casefile_get_value_cnt (cf), case_idx);
-  casefile_append_xfer (cf, &c);
-}
-
-static void
-read_and_verify_random_case (struct casefile *cf,
-                             struct casereader *reader, size_t case_idx) 
-{
-  struct ccase read_case, expected_case;
-  size_t value_cnt;
-  size_t i;
-  
-  value_cnt = casefile_get_value_cnt (cf);
-  get_random_case (&expected_case, value_cnt, case_idx);
-  if (!casereader_read (reader, &read_case)) 
-    fail_test ("Premature end of casefile.");
-  for (i = 0; i < value_cnt; i++) 
-    {
-      double a = case_num (&read_case, i);
-      double b = case_num (&expected_case, i);
-      if (a != b)
-        fail_test ("Case %lu fails comparison.", (unsigned long) case_idx); 
-    }
-  case_destroy (&read_case);
-  case_destroy (&expected_case);
-}
-
-static void
-fail_test (const char *message, ...) 
-{
-  va_list args;
-
-  va_start (args, message);
-  vprintf (message, args);
-  putchar ('\n');
-  va_end (args);
-  
-  exit (1);
-}