-- +---------------------------+
-- |   designer : Tim Pagden   |
-- |    opened: 30 Sep 1993    |
-- +---------------------------+

-- library ieee;
library vfp;
library maths;

package body matrix_class is  
  use maths.maths_class.all;
  use vfp.strings.all;
  use vfp.AWK_functions.all;

  -- sum over k-1 of (a(k-1)-i) * b(i)
  function sum_of_products (
    lower_limit : integer;
    upper_limit : integer;
    a_in : single_vector; 
    b_in : single_vector
  ) return single is       
    variable partial_sum,
             running_total,
             sum : single;
    variable a : single_vector(a_in'length-1 downto 0);
    variable b : single_vector(b_in'length-1 downto 0);
  begin
    a := a_in(upper_limit downto lower_limit);
    b := b_in(upper_limit downto lower_limit);
  
    running_total := 0.0;
    for i in lower_limit to upper_limit loop
      partial_sum := a(i) * b(i);
      running_total := running_total + partial_sum;
    end loop;
    sum := running_total;
    return sum ;
  end sum_of_products;
  
  -- a(I-1) -> out | a(i-1) -> a(i) | data_in -> a(0)
  function shift_fifo (
    fifo : single_vector;
    data_in : single 
  ) return single_vector is       
    variable fifo_out : single;
    variable fifo_queue : single_vector(fifo'length-1 downto 0);
    variable fifo_element : single;
  begin
    fifo_queue := fifo(fifo'length-1 downto 0);
    fifo_element := data_in;
  
    fifo_out := fifo_queue(fifo_queue'length-1);
    for i in fifo_queue'length-1 downto 1 loop
      fifo_queue(i) := fifo_queue(i-1);
    end loop;
    fifo_queue(0) := fifo_element;
    return fifo_queue ;
  end shift_fifo;
  
  -- a(i) -> a((I-1)-i)
  function reverse_order (
    table : single_vector
  ) return single_vector is       
    variable original_table : single_vector(table'length-1 downto 0);
    variable reversed_table : single_vector(table'length-1 downto 0);
  begin
    original_table := table(table'length-1 downto 0);
  
    for i in 0 to original_table'length-1 loop
      reversed_table(i) := original_table((original_table'length-1)-i);
    end loop;
    return reversed_table ;
  end reverse_order;
    
  function "*" (
    multiplicand : single_matrix;
    multiplier   : single_matrix
  ) return single_matrix is
    -- declarations
    variable a : single_matrix(0 to multiplicand'LENGTH(1)-1, 0 to multiplicand'LENGTH(2)-1);
    variable b : single_matrix(0 to multiplier'LENGTH(1)-1, 0 to multiplier'LENGTH(2)-1);
    variable result : single_matrix(0 to multiplicand'LENGTH(1)-1, 0 to multiplier'LENGTH(2)-1);
    variable partial_sum : single_matrix(0 to multiplicand'LENGTH(1)-1, 0 to multiplier'LENGTH(2)-1);
  begin
    a := multiplicand;
    b := multiplier;
    -- first of all check that matrix multiplication is possible
    -- also allow vector * vector, vector * matrix and 
    -- matrix * vector multiplication
    if (a'LENGTH(2) = b'LENGTH(1)) then
      for row in 0 to a'LENGTH(2)-1 loop
        -- num_rows
        for column in 0 to b'LENGTH(1)-1 loop
          -- num_columns
          result(row,column) := 0.0;
          for i in 0 to a'LENGTH(2)-1 loop
            partial_sum(row,column) := a(row,i) * b(i,column);
            result(row,column) := result(row,column) + partial_sum(row,column);
          end loop;
        end loop;
      end loop;
    else
      report "In function *, multiplicand column and multiplier row"; 
      report "lengths are not matched. This is not a VHDL error but";
      report "a mathematical requirement for matrix multiplication."
        severity WARNING;
    end if;
    return result;
  end "*";
  
        -- partial_sum(row,column) := a(row,column) * b(row,column);
        -- sum(row,column) := sum(row,column) + partial_sum(row,column);
        -- sum_of_products(a(row,column), b(column));

  procedure split (
    input_string : STRING; 
    output_array : out integer_vector; 
    separator    : STRING;
    num_fields   : out INTEGER
  ) is
    variable array_as_string      : string_list(0 to input_string'LENGTH);
      -- ideally LENGTH-1, but what happens when the input_string is a single character
      -- you need 0 for the input_str and 1 for the char itself
    variable num_fields_in_string : INTEGER;
    -- variable integer_as_string    : string(1 to 11); -- 32 bit number = sign + 10 digits, = 11
  begin
    split(input_string, array_as_string, separator, num_fields_in_string);
    num_fields := num_fields_in_string;
    for i in 1 to num_fields_in_string loop
      -- integer_as_string := array_as_string(i).all;
      output_array(i-1) := integer'VALUE(array_as_string(i).all);
    end loop;
  end split;

end matrix_class;


<div align="center"><br /><script type="text/javascript"><!--
google_ad_client = "pub-7293844627074885";
//468x60, Created at 07. 11. 25
google_ad_slot = "8619794253";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br />&nbsp;</div>