Interacting with GNU Octave: Variables

Exclusive offer: get 50% off this eBook here
GNU Octave Beginner's Guide

GNU Octave Beginner's Guide — Save 50%

Become a proficient Octave user by learning this high-level scientific numerical tool from the ground up

$26.99    $13.50
by Jesper Schmidt Hansen | June 2011 | Beginner's Guides Open Source

Octave is specifically designed to work with vectors and matrices. In this article by Jesper Schmidt Hansen, author of GNU Octave Beginner's Guide, you will learn how to instantiate such objects (or variables) and how to compare them. Octave also supports more advanced variable types, namely, structures and cell arrays, which we will learn about.

In detail, we will learn how to:

  • Instantiate text string variables
  • Instantiate complex variables
  • Retrieve variable elements through simple vectorized expressions
  • Instantiate structures, cell arrays, and multidimensional arrays
  • Get information about the variables

 

GNU Octave Beginner's Guide

GNU Octave Beginner's Guide

Become a proficient Octave user by learning this high-level scientific numerical tool from the ground up

        Read more about this book      

(For more resources on this subject, see here.)

In the following, we shall see how to instantiate simple variables. By simple variables, we mean scalars, vectors, and matrices. First, a scalar variable with name a is assigned the value 1 by the command:

octave:1> a=1

a = 1

That is, you write the variable name, in this case a, and then you assign a value to the variable using the equal sign. Note that in Octave, variables are not instantiated with a type specifier as it is known from C and other lower-level languages. Octave interprets a number as a real number unless you explicitly tell it otherwise.

In Octave, a real number is a double-precision, floating-point number,which means that the number is accurate within the first 15 digits. Single precision is accurate within the first 6 digits.

You can display the value of a variable simply by typing the variable name:

octave:2>a

a = 1

Let us move on and instantiate an array of numbers:

octave:3 > b = [1 2 3]

b =
1 2 3

Octave interprets this as the row vector:

Interacting with GNU Octave: Variables

rather than a simple one-dimensional array. The elements (or the entries) in a row vector can also be separated by commas, so the command above could have been:

octave:3> b = [1, 2, 3]

b =
1 2 3

To instantiate a column vector:

Interacting with GNU Octave: Variables

you can use:

octave:4 > c = [1;2;3]

c =
1
2
3

Notice how each row is separated by a semicolon.

We now move on and instantiate a matrix with two rows and three columns (a 2 x 3 matrix):

Interacting with GNU Octave: Variables

using the following command:

octave:5 > A = [1 2 3; 4 5 6]

A =
1 2 3
4 5 6

Notice that I use uppercase letters for matrix variables and lowercase letters for scalars and vectors, but this is, of course, a matter of preference, and Octave has no guidelines in this respect. It is important to note, however, that in Octave there is a difference between upper and lowercase letters. If we had used a lowercase a in Command 5 above, Octave would have overwritten the already existing variable instantiated in Command 1. Whenever you assign a new value to an existing variable, the old value is no longer accessible, so be very careful whenever reassigning new values to variables.

Variable names can be composed of characters, underscores, and numbers. A variable name cannot begin with a number. For example, a_1 is accepted as a valid variable name, but 1_a is not.

In this article, we shall use the more general term array when referring to a vector or a matrix variable.

Accessing and changing array elements

To access the second element in the row vector b, we use parenthesis:

octave:6 > b(2)

ans = 2

That is, the array indices start from 1. This is an abbreviation for "answer" and is a variable in itself with a value, which is 2 in the above example.

For the matrix variable A, we use, for example:

octave:7> A(2,3)

ans = 6

to access the element in the second row and the third column. You can access entire rows and columns by using a colon:

octave:8> A(:,2)

ans =
2
5

octave:9 > A(1,:)

ans =
1 2 3

Now that we know how to access the elements in vectors and matrices, we can change the values of these elements as well. To try to set the element A(2,3)to -10.1:

octave:10 > A(2,3) = -10.1

A =
1.0000 2.0000 3.0000
4.0000 5.0000 -10.1000

Since one of the elements in A is now a non-integer number, all elements are shown in floating point format. The number of displayed digits can change depending on the default value, but for Octave's interpreter there is no difference—it always uses double precision for all calculations unless you explicitly tell it not to.

You can change the displayed format using format short or format long. The default is format short.

It is also possible to change the values of all the elements in an entire row by using the colon operator. For example, to substitute the second row in the matrix A with the vector b (from Command 3 above), we use:

octave:11 > A(2,:) = b

A =
1 2 3
1 2 3

This substitution is valid because the vector b has the same number of elements as the rows in A. Let us try to mess things up on purpose and replace the second column in A with b:

octave:12 > A(:,2) = b

error: A(I,J,...) = X: dimension mismatch

Here Octave prints an error message telling us that the dimensions do not match because we wanted to substitute three numbers into an array with just two elements. Furthermore, b is a row vector, and we cannot replace a column with a row.

Always read the error messages that Octave prints out. Usually they are very helpful.

There is an exception to the dimension mismatch shown above. You can always replace elements, entire rows, and columns with a scalar like this:

octave:13> A(:,2) = 42

A =
1 42 3
1 42 3

More examples

It is possible to delete elements, entire rows, and columns, extend existing arrays, and much more.

Time for action – manipulating arrays

  1. To delete the second column in A, we use:

    octave:14> A(:,2) = []

    A =
    1 3
    1 3

  2. We can extend an existing array, for example:

    octave:15 > b = [b 4 5]

    b =
    1 2 3 4 5

  3. Finally, try the following commands:

    octave:16> d = [2 4 6 8 10 12 14 16 18 20]

    d =
    2 4 6 8 10 12 14 16 18 20

    octave:17> d(1:2:9)

    ans =
    2 6 10 14 18

    octave:18> d(3:3:12) = -1

    d =
    2 4 -1 8 10 -1 14 16 -1 20 0 -1

What just happened?

In Command 14, Octave interprets [] as an empty column vector and column 2 in A is then deleted in the command. Instead of deleting a column, we could have deleted a row, for example as an empty column vector and column 2 in A is then deleted in the command.

octave:14> A(2,:)=[]

On the right-hand side of the equal sign in Command 15, we have constructed a new vector given by [b 4 5], that is, if we write out b, we get [1 2 3 4 5] since b=[1 2 3]. Because of the equal sign, we assign the variable b to this vector and delete the existing value of b. Of course, we cannot extend b using b=[b; 4; 5] since this attempts to augment a column vector onto a row vector.

Octave first evaluates the right-hand side of the equal sign and then assigns that result to the variable on the left-hand side. The right-hand side is named an expression.

In Command 16, we instantiated a row vector d, and in Command 17, we accessed the elements with indices 1,3,5,7, and 9, that is, every second element starting from 1. Command 18 could have made you a bit concerned! d is a row vector with 10 elements, but the command instructs Octave to enter the value -1 into elements 3, 6, 9 and 12, that is, into an element that does not exist. In such cases, Octave automatically extends the vector (or array in general) and sets the value of the added elements to zero unless you instruct it to set a specific value. In Command 18, we only instructed Octave to set element 12 to -1, and the value of element 11 will therefore be given the default value 0 as seen from the output. In low-level programming languages, accessing non-existing or non-allocated array elements may result in a program crash the first time it is running2.

This will be the best case scenario. In a worse scenario, the program will work for years, but then crash all of a sudden, which is rather unfortunate if it controls a nuclear power plant or a space shuttle.

As you can see, Octave is designed to work in a vectorized manner. It is therefore often referred to as a vectorized programming language.

Complex variables

Octave also supports calculations with complex numbers. As you may recall, a complex number can be written as z = a + bi, where a is the real part, b is the imaginary part, and i is the imaginary unit defined from i2 = –49491.

To instantiate a complex variable, say z = 1 + 2i, you can type:

octave:19> z = 1 + 2I

z = 1 + 2i

When Octave starts, the variables i, j, I, and J are all imaginary units, so you can use either one of them. I prefer using I for the imaginary unit, since i and j are often used as indices and J is not usually used to symbolize i.

To retrieve the real and imaginary parts of a complex number, you use:

octave:20> real(z)

ans = 1

octave:21>imag(z)

ans = 2

You can also instantiate complex vectors and matrices, for example:

octave:22> Z = [1 -2.3I; 4I 5+6.7I]

Z =
1.0000 + 0.0000i 0.0000 - 2.3000i
0.0000 + 4.0000i 5.0000 + 6.7000i

Be careful! If an array element has non-zero real and imaginary parts, do not leave any blanks (space characters) between the two parts. For example, had we used Z=[1 -2.3I; 4I 5 + 6.7I] in Command 22, the last element would be interpreted as two separate elements (5 and 6.7i). This would lead to dimension mismatch.

The elements in complex arrays can be accessed in the same way as we have done for arrays composed of real numbers. You can use real(Z) and imag(Z) to print the real and imaginary parts of the complex array Z. (Try it out!)

GNU Octave Beginner's Guide Become a proficient Octave user by learning this high-level scientific numerical tool from the ground up
Published: June 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Text variables

Even though Octave is primarily a computational tool, you can also work with text variables. A letter (or character), a word, a sentence, a paragraph, and so on, are all named text strings.

To instantiate a text string variable you can use:

octave:23 > t = "Hello"

t = Hello

Instead of the double quotation marks, you can use single quotation marks. I prefer double quotation marks for strings, because this follows the syntax used by most other programming languages, and differs from the transpose operator.

You can think of a text string variable as an array of characters, just like a vector is an array of numbers. To access the characters in the string, we simply write:

octave:24> t(2)

ans = e

octave:25> t(2:4)

ans = ell

just as we did for numerical arrays. We can also extend existing strings (notice the blank space after the first quotation mark):

octave:26> t = [t " World"]

t = Hello World

You can instantiate a variable with string elements as follows:

octave:27> T= ["Hello" ; "George"]

T =
Hello
George

The string variable T behaves just like a matrix (a two dimensional array) with character elements. You can now access these characters just like elements in a numerical matrix:

octave:28> T(2,1)

ans = G

But wait! The number of characters in the string "Hello" is 5, while the string "George" has 6 characters. Should Octave not complain about the different number of characters? The answer is no. In a situation where the two string lengths do not match, Octave simply adds space characters to the end of the strings. In the example above, the string "Hello" is changed to "Hello ". It is important to stress that this procedure only works for strings. The command:

octave:29 > A = [1 2; 3 4 5]

error: number of columns must match (3 != 2)

leads to an error with a clear message stating the problem.

Higher-dimensional arrays

Octave also supports higher-dimensional arrays. These can be instantiated like any other array, for example:

octave:30> B(2,2,2)=1

B =
ans(:,:,1) =
0 0
0 0

ans(:,:,2) =
0 0
0 1

The previous command instantiates a three-dimensional array B with size 2 x 2 x 2, that is, 23 = 8 elements, by assigning the element B(2,2,2) the value 1. Recall that Octave assigns all non-specified elements the value 0. Octave displays the three dimensional array as two two-dimensional arrays (or slices). We can now access the individual elements and assigned values like we would expect:

octave:31 B(1,2,1) = 42

B =
ans(:,:,1) =
0 42
0 0

ans(:,:,2) =
0 0
0 1

Structures and cell arrays

In many real life applications, we have to work with objects that are described by many different types of variables. For example, if we wish to describe the motion of a projectile, it would be useful to know its mass (a scalar), current velocity (a vector), type (a string), and so forth. In Octave, you can instantiate a single variable that contains all this information. These types of variables are named structures and cell arrays.

Structures

A structure in Octave is like a structure in C—it has a name, for example projectile, and contains a set of fields (or members in C terminology) that each has a name, as shown in the following figure:

Interacting with GNU Octave: Variables

We can refer to the individual structure field using the.character:

structurename.fieldname

where structurename is the name of the structure variable, and fieldname is (as you may have guessed) the field's name.

To show an example of a structure, we can use the projectile described above. Let us therefore name the structure variable projectile, and set the field names to mass, velocity, and type. You can, of course, choose other names if you wish—whatever you find best.

Time for action – instantiating a structure

  1. To set the projectile mass, we can use:

    octave:32>projectile.mass = 10.1

    projectile =
    {
    mass = 10.100
    }

  2. The velocity field is set in a similar fashion:

    octave:33>projectile.velocity = [1 0 0]

    projectile =
    {
    mass = 10.100
    velocity =
    0 0
    }

  3. We can also set the text field as usual:

    octave:34>projectile.type = "Cannonball"

    projectile =
    {
    mass = 10.100
    velocity =
    1 0 0
    type = Cannonball
    }

and so on for position and whatever else could be relevant.

What just happened?

Command 32 instantiates a structure variable with the name projectile by assigning a field named mass the value 10.100. At this point, the structure variable only contains this one field.

In Commands 33 and 34, we then add two new fields to the structure variable. These fields are named velocity and type. It is, of course, possible to keep adding new fields to the structure.

Instead of typing in one structure field at a time, you can use the struct function.

octave:35> projectile = struct("mass", 10.1, "velocity", [1 0 0],
"type", "Cannonball");

The input (called arguments) to the struct function is the first structure field name followed by its value, the second field's name and its value, and so on. Actually, it is not meaningful to talk about a structure's first and second field, and so you can change the order of the arguments to struct and it would not matter.

Did you notice that appending a semi-colon after the command suppresses the response (or output) from Octave?

You can suppress the output that Octave prints after each command by appending a semi-colon to the command.

Accessing structure fields

You can access and change the different fields in a structure by, for example:

octave:36>projectile.velocity(2) = -0.1

projectile =
{
mass = 10.100
velocity =
1 -0.1 0
type = Cannonball
}

In case you have many cannonballs flying around (a rather undesirable situation, of course), it will be practical to have an array of projectile structures. To instantiate an array of two such projectile structures, you can simply copy the entire projectile structure to each array element by:

octave:37> s(1) = projectile;

octave:38> s(2) = projectile;

Notice that to copy a structure you just use the equal sign, so you need not copy each structure field. For accessing the structure elements, you use:

octave:39 s(2).type

ans = Cannonball

Octave has two functions—one to set the structure fields, and one to retrieve them. These are named setfield and getfield:

octave:40> s(2) = setfield(s(2), "type", "Cartridge");

octave:41>getfield(s(2), "type")

ans = Cartridge

You need to assign the output from setfield to the structure. The above example only showed how to instantiate a one dimensional array of structures, but you can also work withmultidimensional arrays if you wish.

You can instantiate nested structures, which are structures where one or more fields are structures themselves. Let us illustrate this via the basic projectile structure:

octave:42 > projectiles = struct("type1", s(1), "type2", s(2));

octave:43 > projectiles.type1.type

ans = Cartridge

Here projectiles has two fields named type1 and type2. Each of these fields is a structure, given by s(1) and s(2) (Commands 37-41).

As you can probably imagine, the complexity and variety of extended structures can become quite overwhelming and we will stop here.

Cell arrays

In Octave, you can work with cell arrays. A cell array is a data container-like structure, in that it can contain both numerical and string variables, but unlike structures it does not have fields. Each cell (or element) in the cell array can be a scalar, vector, text string, and so forth. I like to think about a cell array as a sort of spreadsheetas shown in the figure below:

Interacting with GNU Octave: Variables

GNU Octave Beginner's Guide Become a proficient Octave user by learning this high-level scientific numerical tool from the ground up
Published: June 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on this subject, see here.)

Time for action – instantiating a cell array

  1. To instantiate a cell array with the same data as the projectile structure above, we can use:

    octave:44> projectile = {10.1, [1 0 0], "Cannonball"}

    projectile =
    {
    [1,1] = 10.1
    [1,2] =
    1 0 0
    [1,3] = Cannonball
    }

    The numbers in the square brackets are then the row indices and column indices, respectively.

  2. To access a cell, you must use curly brackets:

    octave:45> projectile{2}

    ans =
    1 0 0

  3. You can have two-dimensional cell arrays as well. For example:

    octave:46> projectiles = {10.1, [1 0 0], "Cannonball"; 1.0, [0 0
    0], "Cartridge"}

    projectile =
    {
    [1, 1] = 10.100
    [2, 1] = 1
    [1, 2] =
    1 0 0
    [2, 2] =
    0 0 0
    [1, 3] = Cannonball
    [2, 3] = Cartridge
    }

  4. To access the values stored in the cell array, simply use:

    octave:47> projectiles{2,3}

    ans = Cartridge

What just happened?

Command 44 instantiates a cell array with one row and three columns. The first cell contains the mass, the second cell the velocity, and the third cell the string "Cannonball", analogous to the structure we discussed above. Notice that the cells in the array can contain different variable types, and the cell array is therefore different from a normal array.

To access the value in a cell, you use curly brackets rather than the usual parenthesis, as shown in Command 45.

You can also work with two-dimensional cell arrays. Commands 46 and 47 show an example of this. Note that to insert an additional row into the cell array, you use semi-colons—just like a numerical array.

Getting information

In this section, we will learn how to obtain information about the variables that have been instantiated. This is particularly useful when you have forgotten the names, sizes, or when you have loaded data from files.

Time for action – using whos

We are working with quite a few variables now. We can list them all with whos:

octave:48>whos

Variables in the current scope:

Attr Name Size Bytes Class
==== ==== ==== ===== =====
A 2x2 32 double
B 2x2x2 128 double
T 2x6 12 char
Z 2x2 64 double
a 1x1 8 double
ans 1x9 9 char
b 1x5 40 double
c 3x1 24 double
d 1x12 96 double
projectile 1x3 42 cell
projectiles 2x3 83 cell
s 1x2 83 struct
t 1x11 11 char
z 1x1 16 double

Total is 81 elements using 648 bytes

What just happened?

As seen above, whos prints out five columns. The first column can have values g or p, which means that the variable is global or persistent. In our case, all the variables are what are named local, which is not stated explicitly by the command whos. A local variable is characterized by being visible and therefore accessible to a given workspace (or scope). In the example above, we have just a single workspace—the top-level workspace—wherein all our variables can be accessed. In fact, we can say that the local variables above define our current top-level workspace.

The second column simply lists the variable names. The sizes of the variables are given in column three in the form: number of rows times number of columns. For example, the scalar variable a (from Command 1) has size 1 x 1, meaning that it has one row and one column. The projectile cell array has one row and three columns, as we know from Command 44.

It is seen from column four that the scalar variable a takes up 8 bytes of memory and is of class double (column five). The fact that the class is a double means that Octave uses double precision for the variables, as mentioned earlier. Recall from Command 26 that the variable t is the text string "Hello World". This string is composed of 11 characters including the blank space, which can be seen from the output above.This is unlike C, where the end of the string is indicated with '\0' and is a part of the character array.

The variable s is a two dimensional array of structures (Commands 37-41) and the variable projectiles is a cell array with same basic "building blocks" as the structure array s. From the table, we observe that it takes up the same memory, so we do not save memory space using one or the other. By the way, does the number of bytes in the structure array s agree with the sum of bytes of the fields?

Below the table, we can see that we use a total of 648 bytes of memory for the variables.

You can call whos with an argument, for example, whos("A"), if you only wish to retrieve information about A. Also, whos has a little brother who. who lists the local variables, but does not list other information.

Size, rows, columns, and length

Rather than listing all available information about a variable, you can get information about its number of rows and columns. The size of A is retrieved by:

octave:49> size(A)

ans =
2 2

since A is a 2 x 2 matrix. In general, size returns the number of rows and columns. You can retrieve these individually if you prefer:

octave:50> rows(A)

ans = 2

octave:51> columns(A)

ans = 2

What happened here should be straightforward to understand.

In Octave, you can also retrieve the length of a variable. We need to understand what that means exactly. If the variable is a vector or text string, the length is the number of elements in the array. If the variable is a higher-dimension array, the length is defined as the maximum number of elements in any of the dimensions. Let us see two examples:

octave:52> length(c)

ans = 3

octave:53> length(T)

ans = 6

The output from Command 53 is the number of columns in the text array. This is returned rather than the number of rows since the variable T has 6 columns but only 2 rows.

Identifying the variable type

Octave can tell you whether a variable is interpreted as a vector, matrix, string, complex number, cell array, and much more. Let us check if Octave actually agrees that the variable a is a scalar:

octave:54>isscalar(a)

ans = 1

Octave returns 1, meaning true (or yes). What about the row vector b?

octave:55>isvector(b)

ans = 1

octave:56>ismatrix(b)

ans = 1

That is a bit strange! b is a (row) vector which is recognized by Octave as seen from Command 55, but why does it interpret b as a matrix as well? A matrix is just an array of elements (a way of organizing numbers).Thus b can be thought of as a matrix with one row and three columns. What will the command ismatrix(a) return? Try it out!

You can check the type of any variable with the istype family. Simply use:
octave:1>is <Tab><Tab>
at the command prompt to see the complete list.

Instead of using the istype, you can use typeinfo. For example, instead of Command 56 we could use:

octave:56>typeinfo(b)

ans = matrix

Deleting variables from the workspace

You can delete variables using the clear command. For example, if you wish to delete the variable A:

octave:58> clear A

You can also use the wildcard *, for example, to delete the variables projectile and projectiles, and any other variable name beginning with p, you can use:

octave:59> clear p*

If you do not specify any variables, the clear, command will delete all the variables, so be very cautious when using the command, because there is no way to retrieve the variables once you have cleared them from the memory (unless you have saved them somewhere else, of course). Try to use whos (or who) to see if the variables were cleared by Commands 58 and 59.

Warning: the command
octave:59> clear
will clear all variables in the workspace.

A few things that make life easier

Imagine that you wish to generate a sequence of numbers in the interval –2.1 to 0.5 (including –2.1 and 0.5) with an incremental spacing of 0.2. This is rather tedious to do by hand and is very error prone, because it involves typing a lot of digits. Fortunately, Octave provides you with a very convenient way to do this (note that we now assign the variable b a new value):

octave:60> b = [-2.1:0.2:0.5]

b =
Columns 1 through 7
-2.1000 -1.9000 -1.7000 -1.5000 -1.3000 -1.1000 -0.9000

Columns 8 through 14
-0.7000 -0.5000 -0.3000 -0.1000 0.1000 0.3000 0.5000

If we had done this by hand instead, we should have typed in:

octave:61> size(b)

ans =
1 14

14 numbers. You can also use negative increments if the interval starting value is larger than the end value. If you do not provide an incremental value, Octave assumes 1.

An important point is that if we have chosen an increment of, say 0.4, in Command 60, Octave will give us a number sequence starting from -2.1, but ending at 0.4.

Often you will find yourself in situations where you need to generate a certain sequence of numbers in a given interval without knowing the increment. You can of course calculate this, but Octave has a functionality to do just that. Let us generate a sequence of 7 numbers in the interval above (that is, from -2.1 to 0.5):

octave:62 > b = linspace(-2.1, 0.5, 7)

b =
-2.1000 -1.6667 -1.2333 -0.8000 -0.3667 0.0667 0.5000

Octave calculates the increment needed, also ensuring that both points in the interval are included.

As we shall see later, the functions ones and zeros are very helpful in cases where you want to generate an array composed of elements with a certain value. For example, to create a 2 x 3 matrix with elements all equal to 1, use:

octave63:> ones(2,3)

ans =
1 1 1
1 1 1

Likewise, to create an array (row vector in this case) with zero elements:

octave64:> zeros(1, 4)

ans = 0 0 0 0

ones and zeros also work with multi-dimensional arrays.

You can just as easily create a diagonal matrix with eye:

octave65:> eye(4)

ans =
Diagonal Matrix
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Notice that we need not specify both the number of rows and the number of columns in Command 65, because a diagonal matrix is only defined for square matrices.

Summary

In this article, you learned how to instantiate vectors and matrices objects (or variables) and how to compare them. In the next article, Interacting with GNU Octave: Operators, we will take it further and see how to perform simple arithmetic with them.


Further resources on this subject:


About the Author :


Jesper Schmidt Hansen

Jesper Schmidt Hansen holds a Ph.D. in soft-material science and is currently doing research in the field of nanofluidics and dynamics at Roskilde University, Denmark. He has been using GNU Octave on a daily basis for many years, both as a student and later as a researcher. The applications have varied from solving partial and ordinary differential equations, simple data plotting, and data generation for other applications, to dynamical system investigations and advanced data analysis.

Books From Packt


Sage Beginner's Guide
Sage Beginner's Guide

R Graph Cookbook
R Graph Cookbook

BIRT 2.6 Data Analysis and Reporting
BIRT 2.6 Data Analysis and Reporting

Statistical Analysis with R
Statistical Analysis with R

Facebook Graph API Development with Flash
Facebook Graph API Development with Flash

Moodle 1.9 Math
Moodle 1.9 Math

Windows Phone 7 XNA Cookbook
Windows Phone 7 XNA Cookbook

Oracle Business Intelligence : The Condensed Guide to Analysis and Reporting
Oracle Business Intelligence : The Condensed Guide to Analysis and Reporting


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Z
9
Y
V
K
h
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software