~kb/sparse

ab6dc9e25ea2a57007fe633997a1344fa5da0b15 — Kim Burgess 3 years ago 602e043
(Partial) specs for Vector
3 files changed, 62 insertions(+), 16 deletions(-)

A spec/sparse/vector_spec.cr
M spec/sparse_spec.cr
M src/sparse/vector.cr
A spec/sparse/vector_spec.cr => spec/sparse/vector_spec.cr +43 -0
@@ 0,0 1,43 @@
require "../spec_helper"

describe Sparse::Vector do
  describe ".new" do
    it "initializes with an empty element set" do
      Sparse::Vector(UInt8, 10000).new
    end

    it "supports pre-allocation for element storage" do
      Sparse::Vector(UInt8, 10000).new initial_capacity: 500
      expect_raises(IndexError) do
        Sparse::Vector(UInt8, 100).new initial_capacity: 500
      end
    end
  end

  describe ".resize!" do
    it "provides a new type with the size encoded" do
      v1 = Sparse::Vector(UInt8, 10000).new
      v1.size.should eq(10000)
      v2 = Sparse::Vector.resize! v1, 100
      v2.size.should eq(100)
    end

    it "keeps the element memory in place" do
      v1 = Sparse::Vector(UInt8, 10000).new
      idx, val = v1.extract_tuples
      v2 = Sparse::Vector.resize! v1, 100
      idx2, val2 = v2.extract_tuples
      idx2.object_id.should eq(idx.object_id)
      val2.object_id.should eq(val.object_id)
    end

    it "truncates element with indixes that exceed the new size" do
      v1 = Sparse::Vector(Int32, 10000).new 1
      v1.set_element 1000, 0
      v1.set_element 9000, 42
      v1.nvals.should eq(2)
      v2 = Sparse::Vector.resize! v1, 5000
      v2.nvals.should eq(1)
    end
  end
end

M spec/sparse_spec.cr => spec/sparse_spec.cr +1 -6
@@ 1,7 1,2 @@
require "./spec_helper"

describe Sparse do
  it "works" do
    false.should eq(true)
  end
end
require "./*"

M src/sparse/vector.cr => src/sparse/vector.cr +18 -10
@@ 7,11 7,13 @@ module Sparse

    # Creates a new `Vector` with *initial_capacity* pre-allocated for elements.
    def initialize(initial_capacity : Int = 0)
      check_index_out_of_bounds initial_capacity
      @idx = typeof(@idx).new initial_capacity
      @val = typeof(@val).new initial_capacity
    end

    private def inititialize(@idx, @val)
    # :nodoc:
    def initialize(@idx, @val)
    end

    # Creates a new `Vector` with the same domain, size and contents.


@@ 31,11 33,11 @@ module Sparse
        %idx, %val = {{vec}}.extract_tuples
        %top = %idx[-1]?
        if %top && %top >= {{size}}
          %del = %idx.bsearch_index { |i| i >= {{size}} }
          %del = %idx.bsearch_index { |i| i >= {{size}} }.not_nil!
          %idx.delete_at %del, %idx.size
          %val.delete_at %val, %cal.size
          %val.delete_at %del, %val.size
        end
        Vector(typeof({{vec}}[0]), {{size}}).new %idx, %val
        Sparse::Vector(typeof(%val[0]), {{size}}).new %idx, %val
      end
    end



@@ 47,7 49,7 @@ module Sparse
    end

    # The dimensionality this vector represents.
    def size : UInt64
    def size : Int
      N
    end



@@ 80,12 82,16 @@ module Sparse
    def set_element(index : Int, value : T) : T
      check_index_out_of_bounds index
      pos = @idx.bsearch_index &.>=(index)
      if @idx[pos] == idx
      if pos.nil?
        @idx << index.to_u64
        @val << value
      elsif @idx[pos] == index
        @val[pos] = value
      else
        @idx.insert pos index
        @val.insert pos value
        @idx.insert pos, index.to_u64
        @val.insert pos, value
      end
      value
    end

    # Remove one stored element.


@@ 108,7 114,7 @@ module Sparse
    end

    # Extract all elements with values assigned.
    def extract_tuples : { Indexable(Idx), Indexable(T) }
    def extract_tuples
      { @idx, @val }
    end



@@ 119,7 125,9 @@ module Sparse
    end

    private def check_index_out_of_bounds(index)
      check_index_out_of_bound { raise IndexError.new "Invalid index (#{index})" }
      check_index_out_of_bounds index do
        raise IndexError.new "Invalid index (#{index})"
      end
    end

    private def check_index_out_of_bounds(index, &)