I spent most of this week, and especially the weekend debugging the Project 6 - Matrix. An apparent simple project, turned out to be only hypothetically simple until I hadn't written the test cases. And as I took a step further to write my first test case to test the constructor, the program failed terribly. Lesson: write test cases as you code the program. The project Matrix is all about using Array class that was been created in the last project, though with a twist; this time Array had to be modified to use allocator's construct/destroy method to create a stack allocated array object. The Matrix, would then be implemented as an Array of Arrays.
The lectures this week, were mostly about containers, and iterators, and how the STL are implemented. The subtleties of C++ during compile time related to various constructors, and assignments didn't make much sense until I ran into the problem of having my Matrix class to work correctly. As it was discussed in the class, the compiler chooses to use a default copy constructor/assignment operation which fails to perform a deep copy for user defined classes. In order to have a deep copy, the programmer is required to explicitly define his/her copy constructor, etc. In context to project Matrix, before I created a copy constructor for the Array, I realized that doing operation such as m[2][3] = y would make m[i][3] = y for all 0 < i < R, where m is the matrix, and R is number of rows. Having developed the copy constructor for the Array overcame the problem.
Besides completing the project, I prepared for the Test #2 for which I read a paper on Unified Modeling Language (UML). It's quite interesting to see how a variety of tools/concepts help people collaborate on a project and successfully execute it.
Sunday, July 26, 2009
Sunday, July 19, 2009
Week 6
This week we studied a number of STL algorithms, and through them enforced the better understanding of different types of iterators: Input Iterator (II), Output Iterator (OI), Forward Iterator (FI), Bidirectional Iterator (BI), and Random access Iterator (RI). Having studied different algorithms such as: Find, MinElement, Transform, Remove, Reverse, Equal, and Accumulate helped in understanding the conventional concept behind different categories of iterators.
We studied the Vector class, which efficiently develops a heap allocated array of objects. The way Vector accomplishes this is by calling the copy constructor of the underlying object class, in contrast to calling the default constructor and the assignment operator as done by stack allocated array. vector uses allocator (memory) to first allocate memory space for the array to be constructed. The allocated memory space is in raw form. Thereafter, it calls the uninitialized_copy/uninitialized_fill which then calls the construct() method; consequently the copy constructor of the underlying value_type. The construct() method calls the placement version of new:
new (p) value_type(v);
A reverse process is pursued while destructing the vector object. It calls, the destory() which calls the destructor for the underlying datatype. It finally deallocates the memory that it assigned for the vector object.
In the last class we studied about iterator_traits, and how meta information inside the Iterator class can be used to infer the return datatype, which in general is not passed as a function template argument.
As for the project, we have been developing an Array class that would implement stack allocated array object and related operations, and methods. Initially we have been getting segfault when trying to call the non-const version of a method from the const method. We overcome the problem by using const_cast casting.
We studied the Vector class, which efficiently develops a heap allocated array of objects. The way Vector accomplishes this is by calling the copy constructor of the underlying object class, in contrast to calling the default constructor and the assignment operator as done by stack allocated array. vector uses allocator (memory) to first allocate memory space for the array to be constructed. The allocated memory space is in raw form. Thereafter, it calls the uninitialized_copy/uninitialized_fill which then calls the construct() method; consequently the copy constructor of the underlying value_type. The construct() method calls the placement version of new:
new (p) value_type(v);
A reverse process is pursued while destructing the vector object. It calls, the destory() which calls the destructor for the underlying datatype. It finally deallocates the memory that it assigned for the vector object.
In the last class we studied about iterator_traits, and how meta information inside the Iterator class can be used to infer the return datatype, which in general is not passed as a function template argument.
As for the project, we have been developing an Array class that would implement stack allocated array object and related operations, and methods. Initially we have been getting segfault when trying to call the non-const version of a method from the const method. We overcome the problem by using const_cast casting.
Saturday, July 11, 2009
Week 5
What an eventful week! Week contained within "containers," and week's tasks iterated over debugging "iterators" :) I spent most of this week working on the project 4 - Integer. And wow, I must say, I learned a lot. The pair programming paid off again. Having worked with the partner simultaneously on the project, allowed me to learn a lot many new concepts of C++; and most importantly their applications and usage.
The project 4 served as a good recall of elementary arithmetic operations: addition, subtraction, multiplication, and division. The project revolves around arbitrary precision integer operations; and the fun part was to calculate the 30th Mersenne prime number (2^132049 - 1) which is around 40000 digits long. And we had it calculated in less than 20 seconds on a Intel Core 2 Duo 2.2 GHz Processor. The optimization technique was to divide the exponent into some power of 2, and multiply them together to find the original power.
There was a doubt though running through me: what's the modulus x % y, when x is a negative number. For instance, -3 % 5 = ? Should it be 2, or -3. While C++ itself calculates it to be -3, while my understanding (as well as Google's) is it should be a positive number. Oh well, we went with the C++ understanding :)
The project 4 served as a good recall of elementary arithmetic operations: addition, subtraction, multiplication, and division. The project revolves around arbitrary precision integer operations; and the fun part was to calculate the 30th Mersenne prime number (2^132049 - 1) which is around 40000 digits long. And we had it calculated in less than 20 seconds on a Intel Core 2 Duo 2.2 GHz Processor. The optimization technique was to divide the exponent into some power of 2, and multiply them together to find the original power.
There was a doubt though running through me: what's the modulus x % y, when x is a negative number. For instance, -3 % 5 = ? Should it be 2, or -3. While C++ itself calculates it to be -3, while my understanding (as well as Google's) is it should be a positive number. Oh well, we went with the C++ understanding :)
Sunday, July 5, 2009
Week 4
This week we went over important concepts such as specialized templates, stacks vs heap allocations, and function pointers.
Specialized templates provide a way of defining secondary templates that can be useful where a known different (and may more efficient) algorithm is to be used to perform a particular task with a particular data type(s). From compiler's perspective, the way function calls are determined is by following order:
(i) Check if there is a non-template version available for the function call. If one does exist call that.
(ii) If the function call is a templatized version, determine the primary template structure.
(iii) Once the primary template structure is determined, check if there is a secondary template version (a specialized function with the matching signature) is available. If a secondary template is available, call that function, else call the primary templatized function.
During the week, we studied how stack allocated arrays differ from heap allocated ones, and in what ways they are similar. Heap allocation offers the flexibility of allocating memory spaces as per the need, but at the same time the programmer is responsible for tracking the allocated memory, and freeing them appropriately when need be so. A rule of thumb is to have as many delete's as there are new's (with appropriate placements). This ensures that there are no memory leakage. A few conceivable problems with heap allocated arrays can be: not freeing memory after use, deleting the wrong memory address, deleting more than needed.
Next, we started on function pointers which in a sense provides a way of customized function calls. The function pointers, allows function calls via pointers that like any other pointer can be changed to call other function.
This week, and the following week I along with my partner will be working on the Project 4 - Integer. The project involves creating a class that implements Big Integer/Arbitrary Precision operations. The idea is to represent numbers with vector/deque where each element is an individual digit, and perform operations on these digits.
Specialized templates provide a way of defining secondary templates that can be useful where a known different (and may more efficient) algorithm is to be used to perform a particular task with a particular data type(s). From compiler's perspective, the way function calls are determined is by following order:
(i) Check if there is a non-template version available for the function call. If one does exist call that.
(ii) If the function call is a templatized version, determine the primary template structure.
(iii) Once the primary template structure is determined, check if there is a secondary template version (a specialized function with the matching signature) is available. If a secondary template is available, call that function, else call the primary templatized function.
During the week, we studied how stack allocated arrays differ from heap allocated ones, and in what ways they are similar. Heap allocation offers the flexibility of allocating memory spaces as per the need, but at the same time the programmer is responsible for tracking the allocated memory, and freeing them appropriately when need be so. A rule of thumb is to have as many delete's as there are new's (with appropriate placements). This ensures that there are no memory leakage. A few conceivable problems with heap allocated arrays can be: not freeing memory after use, deleting the wrong memory address, deleting more than needed.
Next, we started on function pointers which in a sense provides a way of customized function calls. The function pointers, allows function calls via pointers that like any other pointer can be changed to call other function.
This week, and the following week I along with my partner will be working on the Project 4 - Integer. The project involves creating a class that implements Big Integer/Arbitrary Precision operations. The idea is to represent numbers with vector/deque where each element is an individual digit, and perform operations on these digits.
Subscribe to:
Posts (Atom)