Vectors.cpp

// VectorEx.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2007

@import "Ceda/cxPython/cxPython.h"
#include "Ceda/cxUtils/TracerUtils.h"
    
    /*
    id(object) 
    hash( object) 
    help( [object]) 
    enumerate( iterable) 
    dir( [object]) 
    cmp( x, y) 
    isinstance( object, classinfo) 
    iter( o[, sentinel]) 
    repr( object) 
    reversed( seq) 
    setattr( object, name, value) 
    slice( [start,] stop[, step]) 
    sorted( iterable[, cmp[, key[, reverse]]]) 
    str( [object]) 
    sum( sequence[, start]) 
    tuple( [sequence]) 
    type( object) 

    x in s
    x not in s
    s + t
    s * n , n * s
    s[i]
    s[i:j]
    s[i:j:k]
    len(s)
    min(s)
    max(s) 
    
    ==
    !=
    <
    <=
    >
    >=
    is
    is not
    
    s[i] = x
    s[i:j] = t
    del s[i:j]
    s[i:j:k] = t
    del s[i:j:k]
    s.append(x)
    s.extend(x)
    s.count(x)
    s.index(x[, i[, j]])
    s.insert(i, x)
    s.pop([i])
    s.remove(x)
    s.reverse()
    s.sort([cmp[, key[, reverse]]]) 
    */	

@def mPrint(v) = 
{
    print @str(    v = ) + `v`
}

@def mExec(x) =
{
    print @str(x)
    x
    mPrint(L)
}

@def mExec2(x) =
{
    print @str(x = ) + `x`
    mPrint(L)
}

@def mPrint1(msg,v) = 
{
    print msg + ' : ' + @str(v = ) + `v`
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
xvector operations
------------------

In this example, a reflected global function CreateVector() returns a xvector<int32> by value.
The vector is wrapped in a Python object that takes on responsibility for destucting the vector
when the PyObject's ref count falls to zero.

Ceda vectors behave similarly to Python native lists.
*/
namespace VectorOps
{
	$function+ ceda::xvector<ceda::int32> CreateVector()
	{
	    return ceda::xvector<ceda::int32>();
	}
	
	void Run()
	{
		ceda::TraceGroup g("xvector operations");

        PyRun_SimpleString(
            @strx
            (
                CreateVector = rootnamespace.VectorOps.CreateVector
                
                # ---------------------------------------------------------------------------------
                mExec(L = CreateVector())

                # An empty list has truth value False
                mPrint(bool(L))

                # ---------------------------------------------------------------------------------
                # Concatenation with +
                mExec(L = L + [1,2,3])

                # A non-empty list has truth value True
                mPrint(bool(L))
                
                # len(L) gives number of elements in L
                mPrint(len(L))

                # min(L) returns the minimum over all element values in L
                mPrint(min(L))
                
                # max(L) returns the maximum over all element values in L
                mPrint(max(L))
                
                # L*n (or n*L) returns a vector that repeats the elements of L n times
                mPrint(L*5)
                
                # L[i] - the ith element (zero based indexing)
                mPrint(L[0])

                # last element in L
                mPrint(L[-1])   
                
                # L[i1:i2] - the slice corresponding to index range '[i1,i2)'
                mPrint(L[0:2])

                # x in L :  test whether value x appears in L
                mPrint(3 in L)

                # todo: doesnt work!  Dont have a work around!
                # mPrint(100 in L)

                print 'Looping through elements of L'
                for i in L:
                    mPrint(i)
                
                # ---------------------------------------------------------------------------------
                # Assignment to L[i]
                mExec(L[0] = 1000)
                
                # ---------------------------------------------------------------------------------
                # Assignment to L[i1:i2]
                mExec(L[0:1] = [100,200,300,400])

                # ---------------------------------------------------------------------------------
                # del L[i] - delete the ith element of the vector
                mExec(del L[0])
                
                # ---------------------------------------------------------------------------------
                # del L[i1:i2] - delete the slice '[i1,i2)'
                mExec(del L[1:3])
            ));
	}	
}


///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Vector methods
--------------

As for native Python lists, wrapped Ceda Vectors provide the following methods

append(x)
    Add an item to the end of the list; equivalent to a[len(a):] = [x]. 

extend(L)
    Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L. 

insert(i,x)
    Insert an item at a given position. The first argument is the index of the element before which
    to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is 
    equivalent to a.append(x). 

remove(x)
    Remove the first item from the list whose value is x. It is an error if there is no such item. 

pop(i)
    Remove the item at the given position in the list, and return it. 

pop()
    Removes and returns the last item in the list.

index(x)
    Return the index in the list of the first item whose value is x. It is an error if there is no
    such item.

count(x) 
    Return the number of times x appears in the list. 

sort() 
    Sort the items of the list, in place. 

reverse() 
    Reverse the elements of the list, in place. 
*/

namespace VectorMethods
{
	$function+ ceda::xvector<ceda::int32> CreateVector()
	{
	    return ceda::xvector<ceda::int32>();
	}
	
	void Run()
	{
		ceda::TraceGroup g("Vector methods");

        PyRun_SimpleString(
            @strx
            (
                CreateVector = rootnamespace.VectorMethods.CreateVector
                
                # ---------------------------------------------------------------------------------
                mExec(L = CreateVector())

                # ---------------------------------------------------------------------------------
                # L.append(x) - append element x to end of L
                mExec(L.append(1))

                # ---------------------------------------------------------------------------------
                # L.extend(s) - append sequence s to end of L
                mExec(L.extend([2,3,4,5,4]))

                # L.count(x) - returns number of elements with value x in L
                mPrint(L.count(4))

                # L.index(x) - returns smallest i with L[i] == x
                mPrint(L.index(4))

                # ---------------------------------------------------------------------------------
                # L.insert(i,x) - insert element x into L at position i
                mExec(L.insert(1,999))

                # ---------------------------------------------------------------------------------
                # L.remove(x) - Remove first L[i] with L[i] == x
                mExec(L.remove(999))

                # ---------------------------------------------------------------------------------
                # L.pop() - Remove and return last element of L
                mExec2(L.pop())

                # ---------------------------------------------------------------------------------
                # L.pop(i) - Remove and return L[i]
                mExec2(L.pop(2))

                # ---------------------------------------------------------------------------------
                # L.reverse() - reverse elements of L in place
                mExec(L.reverse())
            ));
	}	
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Vector marshalling
------------------
*/

namespace VectorMarshalling
{
	$function+ ceda::xvector<ceda::int32> Create()
	{
	    return ceda::xvector<ceda::int32>();
	}
	
	$function+ void Print1(ceda::xvector<ceda::int32> L)
	{
	    Tracer() << "Print1() : " << L << '\n';
	}

	$function+ void Print2(ceda::xvector<ceda::int32>* L)
	{
	    Tracer() << "Print2() : " << *L << '\n';
	}

	$function+ void Print3(ceda::xvector<ceda::int32>& L)
	{
	    Tracer() << "Print3() : " << L << '\n';
	}

	$function+ void Print4(const ceda::xvector<ceda::int32> L)
	{
	    Tracer() << "Print4() : " << L << '\n';
	}

	$function+ void Print5(const ceda::xvector<ceda::int32>* L)
	{
	    Tracer() << "Print5() : " << *L << '\n';
	}

	$function+ void Print6(const ceda::xvector<ceda::int32>& L)
	{
	    Tracer() << "Print6() : " << L << '\n';
	}

	void Run()
	{
		ceda::TraceGroup g("Vector marshalling");
		
        PyRun_SimpleString(
            @strx
            (
                ns = rootnamespace.VectorMarshalling
                
                # ---------------------------------------------------------------------------------
                mExec(L = ns.Create() + [1,2,3])
                
                ns.Print1(L)
                ns.Print2(L)
                ns.Print3(L)
                ns.Print4(L)
                ns.Print5(L)
                ns.Print6(L)

                ns.Print1([10,20,50])
                #ns.Print2([10,20,50])
                #ns.Print3([10,20,50])
                ns.Print4([10,20,50])
                ns.Print5([10,20,50])
                ns.Print6([10,20,50])
            ));
	}	
}

///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Vector element type mismatches
------------------------------
*/
namespace VectorElementTypeMismatch
{
	$function+ ceda::xvector<ceda::int32> Create1()
	{
	    return ceda::xvector<ceda::int32>();
	}

	$function+ ceda::xvector<ceda::float32> Create2()
	{
	    return ceda::xvector<ceda::float32>();
	}
	
	$function+ void Print1(ceda::xvector<ceda::int32> L)
	{
	    Tracer() << "Print1() : " << L << '\n';
	}

	$function+ void Print2(xvector<float32> L)
	{
	    Tracer() << "Print2() : " << L << '\n';
	}

	void Run()
	{
		ceda::TraceGroup g("Vector Element Type Mismatch");
		
        PyRun_SimpleString(
            @strx
            (
                ns = rootnamespace.VectorElementTypeMismatch
                
                # ---------------------------------------------------------------------------------
                # Expected TypeError exception: Cannot concatenate vector<float32> onto vector<int32>
                mExec(L = ns.Create1() + [1,2,3] + (ns.Create2() + [4,5]))
                
                ns.Print1(L)
            ));
	}	
}

///////////////////////////////////////////////////////////////////////////////////////////////////
namespace VectorEx
{
    void Run()
    {
        VectorOps::Run();
        VectorMethods::Run();
        VectorMarshalling::Run();
        VectorElementTypeMismatch::Run();
    }
}