Author: particle
Date: Tue Jan 10 13:17:49 2006
New Revision: 11062

Modified:
   trunk/src/classes/resizablebooleanarray.pmc
   trunk/t/pmc/resizablebooleanarray.t
Log:
PMC: ResizableBooleanArray
~ modified allocation to 1 bit per item
~ modified push/pop
~ added shift/unshift, freeze/thaw
Adapted from a patch courtesy of Dino Morelli.

Modified: trunk/src/classes/resizablebooleanarray.pmc
==============================================================================
--- trunk/src/classes/resizablebooleanarray.pmc (original)
+++ trunk/src/classes/resizablebooleanarray.pmc Tue Jan 10 13:17:49 2006
@@ -8,10 +8,10 @@ src/classes/resizablebooleanarray.pmc - 
 
 =head1 DESCRIPTION
 
-The C<ResizableBooleanArray PMC> implements an array of resizable
-size, which stores booleans.
+The C<ResizableBooleanArray PMC> implements an array of resizable size,
+which stores booleans.
 It uses the C<Boolean PMC> for all conversions.
-C<ResizableBooleanArray PMC> extends C<FixedBooleanArray PMC>
+The C<ResizableBooleanArray PMC> extends the C<FixedBooleanArray PMC>.
 
 =head2 Functions
 
@@ -25,6 +25,7 @@ C<ResizableBooleanArray PMC> extends C<F
 
 
 #define BITS_PER_CHAR 8
+#define MIN_ALLOC 8 * BITS_PER_CHAR
 
 pmclass ResizableBooleanArray extends FixedBooleanArray need_ext does array {
 
@@ -49,9 +50,17 @@ Returns the integer value of the element
 */
 
     INTVAL get_integer_keyed_int (INTVAL key) {
+        /* Try to make negative index into a real index */
+        if (key < 0) key = SELF.elements() + key;
+
+        /* If it's still negative, we have a problem */
         if (key < 0)
-            internal_exception(OUT_OF_BOUNDS,
+            real_exception(interpreter, NULL, E_IndexError,
                 "ResizableBooleanArray: index out of bounds!");
+
+        /* Adjust key for the current head position */
+        key += PMC_int_val2(SELF);
+
         if(key >= PMC_int_val(SELF))
             DYNSELF.set_integer_native(key+1);
 
@@ -69,9 +78,17 @@ Sets the integer value of the element at
 */
 
     void set_integer_keyed_int (INTVAL key, INTVAL value) {
+        /* Try to make negative index into a real index */
+        if (key < 0) key = SELF.elements() + key;
+
+        /* If it's still negative, we have a problem */
         if (key < 0)
-            internal_exception(OUT_OF_BOUNDS,
+            real_exception(interpreter, NULL, E_IndexError,
                 "ResizableBooleanArray: index out of bounds!");
+
+        /* Adjust key for the current head position */
+        key += PMC_int_val2(SELF);
+
         if(key >= PMC_int_val(SELF))
             DYNSELF.set_integer_native(key+1);
 
@@ -89,38 +106,232 @@ Resizes the array to C<size> elements.
 */
 
     void set_integer_native (INTVAL size) {
+        Parrot_UInt1 *sd;
+        INTVAL newASize;
+        INTVAL currSize = PMC_int_val(SELF) - PMC_int_val2(SELF);
+
+        /* We are already at the requested size. Yay */
+        if(size == currSize) return;
+
         if (size < 0)
-            internal_exception(OUT_OF_BOUNDS,
-                    "ResizableBooleanArray: Can't resize!");
+            real_exception(interpreter, NULL, E_IndexError,
+                "ResizableBooleanArray: Can't resize!");
+
+        newASize = (size / MIN_ALLOC + 1) * MIN_ALLOC;
 
+        /* Nothing allocated yet */
         if ( ! PMC_data(SELF) ) {
-            SUPER(size);
-        }
-        else if (size <= PMC_int_val2(SELF)) {
-            PMC_int_val(SELF) = size;
-            /* we could shrink here if necessary */
-            return;
+            PMC_data(SELF) = mem_sys_allocate_zeroed(newASize);
         }
         else {
-            INTVAL cur, needed;
-            cur = PMC_int_val2(SELF);
-            if (cur < 8192) {
-                cur = size < 2 * cur ? 2 * cur
-                    : (size/BITS_PER_CHAR+1)*BITS_PER_CHAR;
-            }
-            else {
-                needed = size - cur;
-                cur += needed + 4096;
-                cur &= ~0xfff;
-            }
-            PMC_data(SELF) = mem_sys_realloc(PMC_data(SELF),
-                    cur/BITS_PER_CHAR);
-            PMC_int_val(SELF) = size;
-            PMC_int_val2(SELF) = cur;
+            sd = PMC_data(SELF);
+            PMC_data(SELF) = mem_sys_realloc(sd, newASize);
+        }
+
+        PMC_int_val2(SELF) = 0;
+        PMC_int_val(SELF) = size;
+    }
+
+/*
+
+=item C<void push_integer(INTVAL size)>
+
+Extends the array by adding an element of value C<value> to the end.
+
+=cut
+
+*/
+
+    void push_integer (INTVAL value) {
+        INTVAL size = PMC_int_val(SELF) - PMC_int_val2(SELF);
+        DYNSELF.set_integer_native(size + 1);
+        DYNSELF.set_integer_keyed_int(size, value);
+    }
+
+/*
+
+=item C<void pop_integer(INTVAL size)>
+
+Removes and returns the last element.
+
+=cut
+
+*/
+
+    INTVAL pop_integer () {
+        INTVAL size, value;
+
+        if (DYNSELF.elements() < 1)
+            real_exception(interpreter, NULL, E_IndexError,
+                "ResizableBooleanArray: Can't pop from an empty array!");
+
+        size = PMC_int_val(SELF) - PMC_int_val2(SELF);
+        value = DYNSELF.get_integer_keyed_int(size - 1);
+        DYNSELF.set_integer_native(size - 1);
+
+        return value;
+    }
+
+/*
+
+=item C<void unshift_integer(INTVAL size)>
+
+Extends the array by adding an element of value C<value> to the 
+beginning.
+
+=cut
+
+*/
+
+    void unshift_integer (INTVAL value) {
+        Parrot_UInt1 *sdOld, *sdNew;
+
+        /* If int_val2 is smaller than 0, size this thing up */
+        if(PMC_int_val2(SELF) <= 0) {
+            sdOld = PMC_data(SELF);
+            sdNew = mem_sys_allocate_zeroed(
+                ((PMC_int_val2(SELF) / MIN_ALLOC) * MIN_ALLOC) 
+                + PMC_int_val(SELF)
+                + ((PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC)
+            );
+            mem_sys_memmove(sdNew, sdOld + PMC_int_val2(SELF), 
+                PMC_int_val(SELF));
+            mem_sys_free(sdOld);
+            PMC_data(SELF) = sdNew;
+            PMC_int_val2(SELF) += MIN_ALLOC;
+            PMC_int_val(SELF) += MIN_ALLOC;
+        }
+
+        /* Move the head position */
+        PMC_int_val2(SELF)--;
+
+        /* Assign the new value as the first item */
+        DYNSELF.set_integer_keyed_int(0, value);
+    }
+
+/*
+
+=item C<void shift_integer(INTVAL size)>
+
+Removes and returns the first element.
+
+=cut
+
+*/
+
+    INTVAL shift_integer () {
+        INTVAL value;
+        Parrot_UInt1 *sdOld, *sdNew;
+
+        if (DYNSELF.elements() < 1)
+            real_exception(interpreter, NULL, E_IndexError,
+                "ResizableBooleanArray: Can't shift from an empty array!");
+
+        /* Get head value */
+        value = DYNSELF.get_integer_keyed_int(0);
+
+        /* Move the head position */
+        PMC_int_val2(SELF)++;
+
+        /* If int_val2 is bigger than our allocation unit size, size
+            this thing down */
+        if(PMC_int_val2(SELF) >= MIN_ALLOC) {
+            sdOld = PMC_data(SELF);
+            sdNew = mem_sys_allocate_zeroed(
+                ((PMC_int_val2(SELF) / MIN_ALLOC) * MIN_ALLOC) 
+                + PMC_int_val(SELF)
+                + ((PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC)
+            );
+            mem_sys_memmove(sdNew, sdOld + PMC_int_val2(SELF), 
+                PMC_int_val(SELF));
+            mem_sys_free(sdOld);
+            PMC_data(SELF) = sdNew;
         }
+
+        return value;
+    }
+
+/*
+
+=item C<INTVAL elements()>
+
+=cut
+
+*/
+
+    INTVAL elements () {
+        return PMC_int_val(SELF) - PMC_int_val2(SELF);
+    }
+
+/*
+
+=item C<INTVAL get_integer()>
+
+Returns the number of elements in the array.
+
+=cut
+
+*/
+
+    INTVAL get_integer () {
+        return SELF.elements();
     }
 
-}
+/*
+
+=back
+
+=head2 Freeze/thaw Interface
+
+=over 4
+
+=item C<void freeze(visit_info *info)>
+
+Used to archive the string.
+
+=cut
+
+*/
+    void freeze(visit_info *info) {
+        /* XXX Dino - I'm concerned about freezing the entire
+            allocated block of memory, it's dependent on the
+            BITS_PER_CHAR value.
+            Maybe we need to store that during the freeze as well
+            and use it during thaw?
+        */
+
+        IMAGE_IO *io = info->image_io;
+        STRING *s;
+        INTVAL size = (PMC_int_val(SELF) / MIN_ALLOC + 1) * MIN_ALLOC;
+
+        io->vtable->push_integer(INTERP, io, PMC_int_val2(SELF));
+        io->vtable->push_integer(INTERP, io, PMC_int_val(SELF));
+        s = string_from_cstring(INTERP, PMC_data(SELF), size);
+        io->vtable->push_string(INTERP, io, s);
+    }
+
+/*
+
+=item C<void thaw(visit_info *info)>
+
+Used to unarchive the string.
+
+=cut
+
+*/
+    void thaw(visit_info *info) {
+        IMAGE_IO *io = info->image_io;
+        INTVAL headPos = io->vtable->shift_integer(INTERP, io);
+        INTVAL tailPos = io->vtable->shift_integer(INTERP, io);
+        STRING *s = io->vtable->shift_string(INTERP, io);
+
+        PMC_data(SELF) = mem_sys_allocate_zeroed(s->bufused);
+        mem_sys_memcopy(PMC_data(SELF), s->strstart, s->bufused);
+        PMC_int_val2(SELF) = headPos;
+        PMC_int_val(SELF) = tailPos;
+    }
+
+}  /* pmclass */
 
 /*
 
@@ -133,8 +344,15 @@ F<docs/pdds/pdd17_basic_types.pod>.
 =head1 HISTORY
 
 Initial version                  - Matt Fowles 2004-06-11
+
 Changed allocator to double size - Matt Fowles 2004-06-15
 
+Added push_integer               - Bernhard Schmalhofer 2004-10-17
+
+Changed allocation code, added   - Dino Morelli 2005-06-10
+  push_, pop_, shift_, 
+  unshift_integer, freeze, thaw
+
 =cut
 
 */

Modified: trunk/t/pmc/resizablebooleanarray.t
==============================================================================
--- trunk/t/pmc/resizablebooleanarray.t (original)
+++ trunk/t/pmc/resizablebooleanarray.t Tue Jan 10 13:17:49 2006
@@ -6,7 +6,7 @@ use strict;
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 9;
+use Parrot::Test tests => 21;
 
 =head1 NAME
 
@@ -66,6 +66,7 @@ my $fp_equality_macro = <<'ENDOFMACRO';
 .endm
 ENDOFMACRO
 
+
 pasm_output_is(<<'CODE', <<'OUTPUT', "Setting array size");
        new P0, .ResizableBooleanArray
 
@@ -106,6 +107,7 @@ ok 4
 ok 5
 OUTPUT
 
+
 pasm_output_is(<<'CODE', <<'OUTPUT', "Setting first element");
         new P0, .ResizableBooleanArray
         set P0, 1
@@ -135,6 +137,7 @@ ok 2
 ok 3
 OUTPUT
 
+
 pasm_output_is(<<'CODE', <<'OUTPUT', "Setting second element");
         new P0, .ResizableBooleanArray
         set P0, 2
@@ -166,6 +169,7 @@ OUTPUT
 
 # TODO: Rewrite these properly when we have exceptions
 
+
 pasm_output_is(<<'CODE', <<'OUTPUT', "Setting out-of-bounds elements");
         new P0, .ResizableBooleanArray
 
@@ -194,6 +198,7 @@ ok 2
 ok 3
 OUTPUT
 
+
 pasm_output_is(<<'CODE', <<'OUTPUT', "Getting out-of-bounds elements");
         new P0, .ResizableBooleanArray
         set P0, 1
@@ -242,6 +247,7 @@ ok 2
 ok 3
 OUTPUT
 
+
 pasm_output_is(<<"CODE", <<'OUTPUT', "Set via INTs, access via PMC Keys");
 @{[ $fp_equality_macro ]}
      new P0, .ResizableBooleanArray
@@ -288,8 +294,8 @@ ok 3
 ok 4
 OUTPUT
 
-pir_output_is(<< 'CODE', << 'OUTPUT', "check whether interface is done");
 
+pir_output_is(<< 'CODE', << 'OUTPUT', "check whether interface is done");
 .sub _main
     .local pmc pmc1
     pmc1 = new ResizableBooleanArray
@@ -311,8 +317,8 @@ CODE
 0
 OUTPUT
 
-pir_output_is(<< 'CODE', << 'OUTPUT', "push integer");
 
+pir_output_is(<< 'CODE', << 'OUTPUT', "push integer");
 .sub _main
     .local pmc pmc1
     pmc1 = new ResizableBooleanArray
@@ -332,3 +338,603 @@ CODE
 10001
 1
 OUTPUT
+
+
+output_is(<<'CODE', <<'OUTPUT', "creation");
+        new P0, .ResizableBooleanArray
+        set I0, P0
+        print "Created ResizableBooleanArray with "
+        print I0
+        print " elements to start with.\n"
+        end
+CODE
+Created ResizableBooleanArray with 0 elements to start with.
+OUTPUT
+
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "push and pop");
+.sub test :main
+       .local int i, i_elem
+       .local pmc pmc_arr
+       .local int elements
+
+       i = 1
+       pmc_arr = new ResizableBooleanArray
+
+       print_num_elements( pmc_arr )
+
+       push pmc_arr, i
+       print i
+       print_num_elements( pmc_arr )
+
+       push pmc_arr, 0
+       print 0
+       print_num_elements( pmc_arr )
+
+       print_num_elements( pmc_arr )
+
+       i_elem= pop pmc_arr
+       print i_elem
+       print_num_elements( pmc_arr )
+
+       i_elem= pop pmc_arr
+       print i_elem
+       print_num_elements( pmc_arr )
+
+    pmc_arr = 62
+    push pmc_arr, 0
+    push pmc_arr, 1
+    push pmc_arr, 0
+    push pmc_arr, 1
+    i_elem = pop pmc_arr
+    i_elem = pop pmc_arr
+    i_elem = pop pmc_arr
+    print i_elem
+    print_num_elements(pmc_arr)
+.end
+
+.sub print_num_elements
+       .param pmc pmc_arr
+       .local int elements
+       elements= pmc_arr
+       print '['
+       print elements
+       print "]\n"
+       .return()
+.end
+
+CODE
+[0]
+1[1]
+0[2]
+[2]
+0[1]
+1[0]
+1[63]
+OUTPUT
+
+
+pir_output_like(<< 'CODE', << 'OUTPUT', "pop bounds checking");
+.sub 'test' :main
+       P0 = new .ResizableBooleanArray
+       pop I0, P0
+.end
+CODE
+/ResizableBooleanArray: Can't pop from an empty array!.*/
+OUTPUT
+#'
+
+
+pir_output_is(<< 'CODE', << 'OUTPUT', "unshift and shift");
+.sub test :main
+       .local int i, i_elem
+       .local pmc pmc_arr
+       .local int elements
+
+       i= 1
+       pmc_arr= new ResizableBooleanArray
+
+       print_num_elements( pmc_arr )
+
+       unshift pmc_arr, i
+       print i
+       print_num_elements( pmc_arr )
+
+       unshift pmc_arr, 0
+       print 0
+       print_num_elements( pmc_arr )
+
+       print_num_elements( pmc_arr )
+
+       i_elem= shift pmc_arr
+       print i_elem
+       print_num_elements( pmc_arr )
+
+       i_elem= shift pmc_arr
+       print i_elem
+       print_num_elements( pmc_arr )
+
+    pmc_arr = 62
+    unshift pmc_arr, 0
+    unshift pmc_arr, 1
+    unshift pmc_arr, 0
+    unshift pmc_arr, 1
+    i_elem = shift pmc_arr
+    i_elem = shift pmc_arr
+    i_elem = shift pmc_arr
+    print i_elem
+    print_num_elements(pmc_arr)
+
+    # Set same size array is currently
+    pmc_arr = 63
+    print_num_elements(pmc_arr)
+.end
+
+.sub print_num_elements
+       .param pmc pmc_arr
+       .local int elements
+       elements= pmc_arr
+       print '['
+       print elements
+       print "]\n"
+       .return()
+.end
+
+CODE
+[0]
+1[1]
+0[2]
+[2]
+0[1]
+1[0]
+1[63]
+[63]
+OUTPUT
+
+
+pir_output_like(<< 'CODE', << 'OUTPUT', "shift bounds checking");
+.sub 'test' :main
+       P0 = new .ResizableBooleanArray
+       shift I0, P0
+.end
+CODE
+/ResizableBooleanArray: Can't shift from an empty array!.*/
+OUTPUT
+#'
+
+
+output_is(<<'CODE', <<'OUTPUT', "aerobics");
+        new P0, .ResizableBooleanArray
+        set I10, 10000
+
+        set I1, 0
+        set I0, 0
+buildup:
+        ge I0, I10, postBuildUp
+
+        mod I4, I1, 2
+        push P0, I4
+        add I1, 1    # Push P0, mod I1++, 2
+        mod I4, I1, 2
+        push P0, I4
+        add I1, 1    # Push P0, mod I1++, 2
+        mod I4, I1, 2
+        push P0, I4
+        add I1, 1    # Push P0, mod I1++, 2
+
+        pop I2, P0
+        mul I3, I0, 3
+        add I3, 2
+        mod I3, 2
+        ne I2, I3, errFirstPop  # fail if pop != mod I0 * 3 + 2, 2
+
+        pop I2, P0
+        mul I3, I0, 3
+        add I3, 1
+        mod I3, 2
+        ne I2, I3, errSecondPop  # fail if pop != mod I0 * 3 + 1, 2
+
+        set I2, P0
+        add I3, I0, 1
+        ne I2, I3, errBuildLen   # fail if length != I0 + 1
+
+        add I0, 1
+        branch buildup
+postBuildUp:
+
+        set I0, 0
+checkBuildUpLeft:
+        ge I0, I10, postCheckBuildUpLeft
+        set I2, P0[I0]
+        mul I3, I0, 3
+        mod I3, 2
+        ne I2, I3, errLeftGet
+        add I0, 1
+        branch checkBuildUpLeft
+postCheckBuildUpLeft:
+
+        mul I0, I10, -1
+checkBuildUpRight:
+        ge I0, 0, postCheckBuildUpRight
+        set I2, P0[I0]
+        add I3, I0, I10
+        mul I3, 3
+        mod I3, 2
+        ne I2, I3, errRightGet
+        add I0, 1
+        branch checkBuildUpRight
+postCheckBuildUpRight:
+
+        set I0, I10
+tearDown:
+        le I0, 0, postTearDown
+        pop I2, P0
+        sub I3, I0, 1
+        mod I3, 2
+        ne I2, I3, errTearDown
+
+        sub I0, 1
+        branch tearDown
+postTearDown:
+
+        print "I need a shower.\n"
+        end
+errFirstPop:
+        print "FAILED: first pop\n"
+        bsr info
+        end
+errSecondPop:
+        print "FAILED: second pop\n"
+        bsr info
+        end
+errBuildLen:
+        print "FAILED: buildup length\n"
+        bsr info
+        end
+errLeftGet:
+        print "FAILED: left get\n"
+        bsr info
+        end
+errRightGet:
+        print "FAILED: right get\n"
+        bsr info
+        end
+errTearDown:
+        print "FAILED: tear down cap\n"
+        bsr info
+        end
+info:
+        print "Found: "
+        print I2
+        print "\nWanted: "
+        print I3
+        print "\n"
+        ret
+CODE
+I need a shower.
+OUTPUT
+
+
+my $SPEEDUP = $ENV{RUNNING_MAKE_TEST} ? "gc_debug 0\n" : "";
+output_is($SPEEDUP . <<'CODE', <<'OUTPUT', "direct access");
+    new P0, .ResizableBooleanArray
+    set S0, ""
+    set S1, "abcdefghijklmnopqrst"
+    set I10, 100000
+    set I0, 0
+lp:
+    mod I2, I0, 2
+    set P0[I0], I2
+    inc I0
+    mod I9, I0, 100
+    ne I9, 0, lp1
+    # force GC => 142 DOD + 142 collects / 10^5 accesses
+    new P1, .PerlArray
+    set P1[I0], I0
+    concat S0, S1, S1
+    set S2, S0
+    set S0, S1
+    set S2, ""
+lp1:
+    le I0, I10, lp
+
+    set I0, 0
+lp2:
+    mod I2, I0, 2
+    set I1, P0[I0]
+    ne I2, I1, err
+    inc I0
+    le I0, I10, lp2
+    print "ok\n"
+    end
+err:
+    print "err: wanted "
+    print I0
+    print " got "
+    print I1
+    print "\n"
+    end
+CODE
+ok
+OUTPUT
+
+
+output_is(<<'CODE', <<'OUTPUT', "direct access 2");
+    #new P0, .IntList
+    new P0, .ResizableBooleanArray
+    set I10, 1100000
+    set I0, 1
+lp1:
+    add I1, I0, 5
+    mod I2, I1, 2
+    set P0[I0], I2
+    add I3, I1, I0
+    mod I2, I3, 2
+    push P0, I2
+    shl I0, I0, 1
+    inc I0
+    le I0, I10, lp1
+
+    set I0, 1
+lp2:
+    add I1, I0, 5
+    mod I5, I1, 2
+    # check at I0
+    set I2, P0[I0]
+    ne I2, I5, err
+    add I4, I0, 1
+    # and pushed value at I0+1
+    set I4, P0[I4]
+    add I3, I1, I0
+    mod I5, I3, 2
+    ne I5, I4, err
+
+    shl I0, I0, 1
+    inc I0
+    le I0, I10, lp2
+    print "ok\n"
+    end
+err:
+    print "not ok "
+    print I0
+    print " "
+    print I1
+    print " "
+    print I2
+    print " "
+    print I3
+    print " "
+    print I4
+    print " "
+    print I5
+    print " "
+    print I6
+    print " "
+    print I7
+    print "\n"
+
+    end
+CODE
+ok
+OUTPUT
+
+
+output_is(<<'CODE', <<'OUTPUT', "sparse access");
+    new P0, .ResizableBooleanArray
+       set I10, 110000
+       set I0, 1
+lp1:
+       add I1, I0, 5
+    mod I9, I1, 2
+       set P0[I0], I9
+       add I3, I1, I0
+    mod I9, I3, 2
+       push P0, I9
+       shl I0, I0, 1
+       inc I0
+       le I0, I10, lp1
+
+       set I0, 1
+lp2:
+       add I1, I0, 5
+    mod I9, I1, 2
+       # check at I0
+       set I2, P0[I0]
+       ne I2, I9, err
+       add I4, I0, 1
+       # and pushed value at I0+1
+       set I4, P0[I4]
+       add I3, I1, I0
+    mod I9, I3, 2
+       ne I9, I4, err
+
+       shl I0, I0, 1
+       inc I0
+       le I0, I10, lp2
+       print "ok 1\n"
+
+       # now repeat and fill some holes
+
+       set I0, 777
+lp3:
+       add I1, I0, 5
+    mod I9, I1, 2
+       set P0[I0], I9
+       add I0, I0, 666
+       le I0, I10, lp3
+
+       set I0, 777
+lp4:
+       add I1, I0, 5
+    mod I9, I1, 2
+       # check at I0
+       set I2, P0[I0]
+       ne I2, I9, err
+
+       add I0, I0, 666
+       le I0, I10, lp4
+       print "ok 2\n"
+       end
+err:
+       print "not ok "
+       print I0
+       print " "
+       print I1
+       print " "
+       print I2
+       print " "
+       print I3
+       print " "
+       print I4
+       print "\n"
+
+       end
+CODE
+ok 1
+ok 2
+OUTPUT
+
+TODO: {
+    local $TODO = "this is broken";
+
+output_is(<<'CODE', <<'OUTPUT', "check for zeroedness");
+    new P0, .ResizableBooleanArray
+    set I0, 0
+lp1:
+    push P0, 0
+    inc I0
+    lt I0, 100, lp1
+
+    set I2, 10000
+    #set I0, 100
+    set P0, I2
+lp2:
+    set I1, P0[I0]
+    ne I1, 0, err
+    inc I0
+    lt I0, I2, lp2
+    print "ok\n"
+    end
+err:
+    print "Found non-zero value "
+    print I1
+    print " at "
+    print I0
+    print "\n"
+    end
+CODE
+ok
+OUTPUT
+
+
+output_is(<<'CODE', <<'OUTPUT', "pop into sparse");
+    new P0, .ResizableBooleanArray
+       set I10, 100
+       set I0, 0
+       # push some values at start
+lp1:
+    mod I5, I0, 2
+       push P0, I5
+       inc I0
+       lt I0, I10, lp1
+
+       # create sparse
+       set I0, 100000
+       set I1, 1000
+    mod I5, I1, 2
+       #set P0[I0], I1
+       set P0[I0], I5
+       inc I1
+lp2:
+       # push some values after hole
+    mod I5, I1, 2
+       push P0, I5
+       inc I1
+       le I1, 1100, lp2
+       dec I1
+
+       set I3, P0
+lp3:
+       set I4, P0
+       ne I3, I4, err1
+       pop I2, P0
+       dec I3
+    mod I5, I1, 2
+       ne I2, I5, err2
+       gt I3, I0, cont1
+       lt I3, I10, cont1
+       set I1, 0
+
+       gt I3, I10, lp3
+       set I1, I10
+
+cont1:
+       dec I1
+       eq I1, 0, ok
+       branch lp3
+ok:
+       print "ok\n"
+       end
+err1:   set S0, "len"
+       branch err
+err2:
+       set S0, "val"
+err:
+       print "nok "
+       print S0
+       print " "
+       print I0
+       print " "
+       print I1
+       print " "
+       print I2
+       print " "
+       print I3
+       print " "
+       print I4
+       print " "
+       print I5
+       end
+CODE
+ok
+OUTPUT
+
+
+output_is(<<'CODE', <<'OUTPUT', "clone");
+    new P0, .ResizableBooleanArray
+       set P0[0], 1
+       set P0[5000], 1
+       clone P1, P0
+
+       set I0, P0[5000]
+       eq I0, 1, ok_1
+       print "nok 1 "
+ok_1:
+       pop I0, P0
+       eq I0, 1, ok_2
+       print "nok 2 "
+ok_2:
+       set I0, P0
+       eq I0, 5000, ok_3
+       print "nok 3 "
+ok_3:
+       set I0, P1
+       eq I0, 5000, ok_4
+       print "nok 4 "
+ok_4:
+       set I0, P1[5000]
+       eq I0, 1, ok_5
+       print "nok 5 "
+ok_5:
+       pop I0, P1
+       eq I0, 1, ok_6
+       print "nok 6 "
+       end
+ok_6:
+       print "ok\n"
+       end
+CODE
+ok
+OUTPUT
+
+} # TODO

Reply via email to