 of charts, this is the distribution of marks in quiz 1 after the crib session. So, it is little steeper than I wanted. So, that is why we scale down quiz 1 from 14 to 7. So, that you know the low part of the curve does not suffer unnecessarily, may be to the first exam will be too difficult. This is midterm before cribs. So, there is a bit more leveling out at the mid range. So, this is considered reasonably healthy curve. So, midterm will stay at 16 and you know we have been doing histogram equalization and so on. So, you can figure out what to do with it. So, that is the two exam status. You can see the highest is actually full marks. So, there are people who are doing pretty well. Now, today what is the plan? So, the plan is to keep talking about separate compilation and more system details about you know compiling, linking and so on. Few compiler flags that will help you along. And because the other the second lecture today won't happen, I need to even know about this actually. So, instead of proceeding further on to recursion and so on dynamic programming, what I thought I would do is discuss one or two interesting problems. In particular, the Wednesday lab lead to one such issue. The one where you are given a what is called a semi magic square. So, a magic square is one where the rows, columns and diagonals all add up to the same number. A semi magic square is where you exclude the diagonals from that rule. So, all the each row and each column adds up to the same positive integer. So, there is a theorem which says that any semi magic square can be decomposed into a sum of permutation matrix. So, permutation matrix is one where it is a n by n square matrix where each row and each column has exactly one, one in it. Think like nine queens sort of problem. So, it is not too difficult to see why it is an intuitive theorem. You give me a matrix with only non negative integers in it and every row and every column adds up to exactly the same positive integer. You can keep you know subtracting. So, suppose given such a matrix where each row and each column adds up to some constant c integer. I manage to subtract one permutation matrix out of it. So, that the row and column sums decrease to c minus 1 then you can keep doing it. So, the basic step is how do you subtract one permutation matrix problem, but that leads to a non-trivial issue. So, we will see how to solve these things. So, for the lab itself will of course try to normalize it based on relative difficulties of labs in particular for labs which had unintended hardness here and there, but I was not looking for necessarily a polynomial time solution. The first part did not say anything about complexity. If you gave a very inefficient algorithm, but which was correct you would get full marks. Anyway, we will come back to that once we are done with the primary part of the lecture. So, today we will mostly continue with discussing system detail, how to split up your code into different files and how to compile them separately and so on. And then we will get to that interesting multiple loop problem whatever. So, I will just quickly retrace some of the things we talked about last time just in case you forget. Your process in the computer is allocated three memory segments. Each is logically numbered from some base address upward. And just for simplicity we will assign arbitrary base addresses to each of these segments. We will say start main from 1000, some function you wrote from 2000, etc. It does not matter, but the data and stack segment are totally different from the code segment and the hardware prevents you from making illegal accesses into one of the segments in a way that you should not. So, the code segment stores executable code in a read only logic. So, you cannot write that code normally. The data segment is called the heap and it contains a jumble of bits which represent things like strings, vectors, matrices and all those things. And later on we will see how to allocate space out of the heap for yourself. Currently we are doing it only through classes that other people wrote for us like vector and string. But soon enough we will see how to allocate and manipulate memory from the heap and then return it to the system. It is a dangerous game. The heap is entirely under your control and you can trample over the bits and mess up what those bits mean. But we will see that in a couple of weeks. The stack segment is what we are focusing on now. It is a memory used for A, communication between the caller and callee. B, keeping track of pending work. So, when the callee finishes, how to return back correctly to the caller. And B, able to do this in a nested fashion in case you have nested function calls. But there is another invisible bullet which I have not written here, which is every time you declare this kind of a scope. So, suppose you are going along your code and you had for in something. Remember this int x has visibility only in this scope and it disappears after there. Inside you may well declare float y, etc. These x and y, these are local short lived variables. They are in effect. So, x is in effect throughout the for loop. y is in fact even more short lived. y dies and gets reallocated every iteration of the for loop. So, in fact, there is like this invisible currently around here and y is declared inside that. Whereas, x is lives throughout the execution of the for loop. So, where are these allocated? The stack is also used to allocate these. And the reason is very clear. The stack is designed for last in first out operation. And clearly these curlies have to be properly nested for your program to compile and give executable code. The discipline is that you have to close curlies in matching pairs. And therefore, it is a natural paradigm for a stack. As soon as you enter a curly, you can allocate space for all the variables declared in that scope. And when that curly bracket is closed, you can free up the memory of the stack. So, the stack is used for a whole bunch of things. The activation records that communicate data between the caller and the callee. It is also used in the same package basically for saved registers. Remember the caller has a particular state of all the registers in the system. If the callee goes and mangles them, then the callee should restore them before transferring control back to the caller. Otherwise, the caller is completely lost. Its state has been completely destroyed. And the third thing is these variables. I think sometimes they are called automatic variables, but let us call them local variables declared in some scope. So, anytime there is a scope, something like this happens. The scoping can be static. It can be visible through the use of nested scopes. Or it could be dynamic. It could be a result of one function calling another one. So, those are the purposes of the stack. The stack is used whenever there is this natural nesting. You get in somewhere, you get out of it. And then we saw that in case of a call, here is a simplified diagram of how the stack is manipulated. The stack pointer always points to the top of the stack. And in this picture, it is kind of drawn inverted. Addresses increase upward from the base of the stack segment. So, the stack pointer is a special register. You cannot directly manipulate it. The program counter is a special register. The program counter is manipulated only through executing an instruction in which case PC advances to the next instruction or through jumps. If you jump, then the program control will be set to wherever you are jumping. Now similarly, the SP is manipulated only by calls and returns. Or by opening scope and removing scope, closing a scope. So, if main calls fund 1 and fund 1 calls fund 2, initially the stack is empty. Main is running. There is nothing more to do after main returns. The communication between main and fund 1 is packaged into that activation record plus save registers, if any. And stack pointer is bumped up to represent that there is now something in the stack and it is not empty. Then when fund 1 calls fund 2, there is an additional record pushed on top of the previous record which stores this interaction between fund 1 and fund 2. When fund 2 returns, perhaps without calling anyone else, then this record can be taken off from the stack because fund 2 is done. And then when fund 1 returns, the stack becomes empty again. So, it is a discipline of growing and shrinking and growing and shrinking as the code executes. So, what goes into this activation record? Here is a simple example. Although for functions with lots of parameters, it will get more complicated. In case of the absolute function which takes an integer by value and the returns another integer, it is very simple. The activation record has three fields. One is what value is input into abs. Out is what value is output from abs back to the caller. And the last is this code address to jump to when the return happens. And the code for abs itself looks like the Lord, the stable here. The left-hand column gives you the program counter or rather the memory address of the instruction. So, the very first address where abs is executed is 2000 in this example. And the first thing you do is you copy the stack dot top dot in, the in field of the activation record into a register A. And then 2001 says if A is already positive, then you do not need to do 2002. You can skip to 2003. That is what changes the PC if necessary. Otherwise in 2002, you flip the sign of A register A. In instruction at 2003, we write out the resulting value to wherever abs is supposed to send its output, which is stack dot top dot out. So, in that field in this slot here, space to write return value, you write out A. And then in 2004, you again change the PC by going to the to-do field of the table. So, and that can be used in this case, yes. Sir, the program is not in U A, the constraint not in U A. Depends on what the value is called with. So, if it is called with minus 3, then it will change A. That is right. It does not change the input thing, yes. Sir, in 2002, second number 2002, it is equal to minus 4. Yes. Sir, how can we change A, sir? You are changing the A that is inside abs itself, that is perfectly allowed. And then I am returning it back throughout. The caller's value is not changed, that is correct. You are only finding either A or minus A and returning it from abs. Sir, the function itself is not changing the local A. The function is changing the local A as in a register, in this case. Think of A as a register. That register is changed, it is negated. And that negative value is written out to the top of the stack. Sir, at the end of the main function, we write the value of A. No, but you cannot. Remember, the signature of abs is int abs int. So, the signature says int abs int A. Therefore, in main, when you call it, you have to say something like say x equal to minus 3, but then you say y equal to abs x. So, this will not be changed, but whatever is returned, that will be the negative value. So, what will be A and x equal to minus 3? Why will be 3? Yes. And that is because abs communicates its output value through this stack.top.out. That is why. Now, you could work out an example where we pass by deference. In case of pass by deference, there has to be in that infield, there has to be a flag saying that this is actually an address. So, if you say abs becomes changes signature to say void make abs int and y with the intention that abs will actually flip the sign of the input modified. Then the thing that is passed in to in has to be an address. And when you flip the sign here, you have to actually access the cell pointed by that address. So, anytime you have parameters passed by reference into a body of a function and the function is changing the value of that parameter, you have to look up that address rather than using in directly. So, here is the call sequence. So, the statements leading up to the call is in yellow. The call itself is just a transfer of program counter from one place to the other. That is shown in pink. And then after the call returns to the caller, the clean up code of the caller is showed in blueish. So, in this particular code shown on the left, there are actually two calls to abs once with an argument of minus 3, which is x, once with the call of 5, which is y. So, and those two calls are shown in this color coding. So, yellow is going in, blue is coming out and then yellow is going in again. So, the only difference between these two calls is that stack.top.in is assigned two different values x and y, but also that the to do, which is where to return is said differently. In the first call it is 1005, the first clean up code in the second case is 10010, which is the second clean up code. That is all. And the rest is fairly simple. So, that is how the stack works. And it is kind of important to know how the stack works because C and C++ gives you all kinds of low level handles into things like these, especially when you come to pointers. You will realize that if I pass a integer pointer into a function and I start doing pointer arithmetic on it, I may be able to write things into the stack. So, here the intention is that you return to 1005 and that information 1005 and 10010 goes on the stack in the to do feed. If somehow I could write code which in the callie modifies the stack, then the callie may not return to the caller properly. Remember the callie sees the top of the stack and at the end of the callies code, it says go to stack.top.to do. Suppose the callie could write stack.top.to prove. Then the callie could jump anywhere. This is how you write viruses. You provide some kind of a routine to someone which you think is useful. Like here is my image manipulation program. And somewhere hidden there is a function which manipulates the stack in the callie so that when the callie returns, it doesn't return to a safe point in the caller from which it has called. It returns into system code inside the operating system and messes up your machine. So, stack protection is a big issue. In languages like C and C++, it's relatively easy to mangle the stack and then make the machine vulnerable to all kinds of virus attacks. So, vast majority of virus attacks are through stack manipulation. So, you look at some of that when you do pointers. So, coming back to separate compilation units, we saw an example where we wrote a matrix printer function. And there are two parts in which you write it. One is the specification file or the signature file, which is the .HPP or .H file that your customers are supposed to see. They don't see the implementation. It just gives you the signature of print matrix, print whatever CS 101, which gives you the input and output signature so that people can use the routine without knowing how it's implemented. And the corresponding .HPP file actually implements the printing action. And it's good to separate those out also because then the compiler can compile your .HPP file only once. And then whenever it's required, the resulting object file can be linked in. So, the broad architecture is that your C++ source, when you give the .C flag only compiles into what's called an object file. This is a compiled machine language version of the C++ source, except that it doesn't necessarily have a main method. So, you cannot run it. It just provides some functions and variables and so on. Now, you do that for a bunch of object files. So, the library writer does this. And in some cases, if the number of object files is very large, you can again combine all this using again the .G++ command or a command called ld, which we will look into later on, which is a linker, which makes a library file. A library file is nothing but a whole bunch of .o files in one package with some kind of a lookup table saying if you need this function, it's here. That's all. And this is usually named with an extension of .a for archive or .so for shared object. In case of windows, this file would be called with an extension of .dll. So, .dll in windows is the same as .so and .a in Linux world. In fact, .so. So, .as are what are called static libraries, .so are what are called dynamic libraries, which is the same as .dll. Now, so this is what the library writer has done. And on this side, here's the user or you. You write something like a main .cpp. Now, remember at the interface of all this is the ..hpp or header files. They are used on both sides. They keep the color and the collie consistent in the signatures of the functions. So, the main .cpp has to include the same hpp file or files. Then it does the calling. This is compiled into main .o. And then main .o and either all these object files or the single library file. This is, this goes into a last compilation or linking stage. Either g plus plus itself or linker into a .out. So, that's how this is done. And we saw how to issue common line arguments to do this. Just to give short names. Let's say that was what matrix printer. So, let's say mp .o. And this was main .o. So, you would finally say g plus plus main .o and mp .o. And if you want to save it to a different file, you would say main .exe. Instead of a .out, you can give any name you want. Now, two more small things. One is this flag called dash i. The other is this flag called dash l. And then there's also dash small l. So, let me explain each of those. So, the default place where your g plus plus compiler looks for include files. That is decided by dash i. So, there are two ways to include. One is to say hash include and then give angles. The other is to give quotes. If you say angle, that means look into system areas that are installed as part of the operating system of the machine. Now, the default starting point for the system areas is slash user slash include. So, if you go into that, directory you'll see hundreds of thousands of error files to be used in C and C plus plus programs. When you say quote, that means non-system, your stuff. So, the default is to just look into the same directory as you're running g plus plus in or wherever the c plus plus file is. But if you want to add some places to look, you have to give them as arguments to dash i. So, to give an example, suppose this library is already written and let me give you a directory layout under your home directory. So, let's say here's your home directory slash home slash u and then under it, there are two directories. So, here is some fancy, say, easy BMP or something. A directory called easy BMP and you're writing a project for say, I don't know, automatically cropping images, auto crop. And you want to use easy BMP stuff in it to read and write BMP images. So, let's say easy BMP is offered to you as two files, easy BMP dot h and easy BMP dot a. Maybe multiple c plus plus files have been compiled and put into one archive library file as I was saying. Inside auto crop, we have written your, say, main dot cpp. Now, you have just unpacked this library by fetching it from the internet. You have not set it up in the system as a whole. So, in this case, main dot cpp will have to include easy BMP dot h. And sure, one thing you could do is you could write out that include statement as in the following messy form. So, you could say hash include code dot dot slash easy BMP dot h. That will work, but it will work only if the directories were in that configuration. If tomorrow enough people are using easy BMP so that the sysad comes and installs it in user include, then if you keep this particular path in your c plus plus file, your compiler will no longer find it. This will work only if main dot cpp's parent directory has a sub directory, sorry. See, I already made a mistake here. Should be that. Has a parent directory called easy BMP, which has a file called easy BMP dot h. So, that is not a very nice way to code. The better approach is to say to g plus plus that look into in the make file, something like either the absolute path home u easy BMP or at least here you can say dot dot slash easy BMP. So, if your make file is here or if you are issuing the command in this directory, it tells the g plus plus compiler to look for include files also in this directory. And therefore, your include statement will now become just easy BMP dot dot h. So, this flag in conjunction with a simple file name will do the right thing, because this flag will tell the g plus plus compiler to look into dot dot slash easy BMP where easy BMP dot h will be found. Now, generally speaking, you do not want any or at least long paths with slashes inside the include. You have to decide what is natural root point from which things are included and use that in the dash i and then put the rest in there. So, the concatenation of this and that should lead to the right place. Now, after all this I have to do some linking. So, linking means that in the last stage where main dot o has to be combined with easy BMP dot a to give me a dot out or main dot exe. To do that, you again have to tell the g plus plus compiler where libraries are to be found. The default place where libraries are look for is user lib. If you want to add more places where the compiler or linker has to look for other linker has to look for more libraries, you have to add it to the dash l flag capital L. So, here again you will say easy BMP. So, that will tell the compiler in the linking phase to look for dot a files or dot so files in dot dot slash easy BMP and then the weird stuff the small l file. This is actually a weird legacy thing, embarrassing. So, what is actually done is this dot a files always start with lib. So, you will really never compile all the easy BMP sources to anything that is not start with a lib name. So, this library so it is lib whatever else you want. And what you do here is you take out that part and after dash l you have to only give the rest without the dot a. So, what the compiler and linker will do is that it will take this name it will prepend lib it will append dot a or dot so and then look for that in any of the directories listed on the capital. So, that is how it goes and as in the last couple of minutes I have been messing around with compiler versus linker. So, what is the difference? Technically, you compile using g plus plus you link using ld, but g plus plus has dozens of default places where it looks for includes dozens of default places where it looks for libraries not just user lib there are others like user local lib and so on. So, you do not want to keep on typing them into ld. So, when g plus plus realizes that it has a linking job on its hands it calls ld with all those proper parameters. So, generally as an end user you will not call ld directly, but it is the linker which works in the last phase to use these arguments. The c plus plus compiler uses that information. Once the source is compiled the job of the include files is done it is not required anymore. Once you have dot o and dot a and dot so files the remaining job is only for a linker, but the linker is again invoked by g plus plus because it is easier to find things that way where things have been kept. So, you do not need to worry about invoking ld directly on your own. We will always do things to g plus plus only. So, that is how it works. So, summary is set up your directory parts to be clean. This is your project that is stuff that other people have provided that comes typically in two parts the headers and the library files. It could be headers and a lot of dot o files which is inconvenient a single output file would be nice single dot a dot so file. And then you include it you the actual include statement should have a simple file name. So, that if tomorrow you want to relocate this directory somewhere else all you have to change is the flag parts in one place. You do not have to change so many include statements. The include only happens once that is not changed. The base of the include can be changed anytime in your g plus plus invocation or in the make file. So, usually the you want to even type this on the comment line every time you would actually in this directory will create a file called make file. That file will include information about include and library parts once and that can be used again and again. We will see an example of that. Any questions? So, how does make do its job? Now, the basic question make asks is when we change one file or a few files in a large project which other files need to be compiled or processed or linked again. The file system itself provides no consistency check. If you compiled a file called a dot out and you changed matrix printer dot cpp which was one of the sources going into a dot out the operating system does not interfere with your running an old executable. The executable once created is separated from the source. So, a make file gives a formal specification of this dependencies. So, it is easy to visualize the dependencies through a graph like this. It is a detected acyclic graph. There is no cycle. So, at the bottom are things that you change and going upward are derived files which are outputs of processing your input files. So, you write Gaussian dot cpp which happens to use a function whose signature is given in matrix printer dot hpp. Therefore, Gaussian dot o depends both on Gaussian dot cpp and matrix printer dot hpp. Any one of those changes you are affected. Similarly, the implementation matrix printer dot o depends on matrix printer dot cpp and the matrix printer dot hpp. Now, and then it goes upward. So, you need both the dot of files to create the Gaussian dot exe file. Now, the point is whenever you change one of these files, there is an upward percolating effect. Anything that you can reach in this graph following edges from that point upward is affected and makes job is to trace that sub graph. Make looks at this dependency structure and then it looks at what all files you have changed. It sort of pours ink into those and the ink spreads upward to the root. And for every note that is affected, it has to do it in order in a suitable topological order so that you clean up the frontier as you go. Now, how does the make file has a bunch of rules and actions. A rule has the form target colon dependency list. So, in the language of this graph, a target may be the matrix printer dot o colon dependencies matrix printer dot hpp and matrix printer dot cpp. So, the target node and then incoming neighbors are listed on the left and right side of the colon. And an action is just a program to run. Same as you would run from your bash prompt. For example, compile using g plus plus or link using g plus plus. Now, how does make do its job? If any file on the dependency list is newer than the target, then it has to be done that. Now, the important issue is timestamp. Make works by comparing the last modified timestamp on the files. Even if the file hasn't changed, but its timestamp has changed, make has no way of doing it. If you opened your c plus plus file and added a comment, which would in no way affect the object file, make doesn't know. If the file is modified at all, make will redone that task just to be safe. So, and then make will schedule this wave front of updates in the sense that if make finds that matrix printer dot hpp has been modified, then in no particular order, make can run redone the compilation of Gaussian dot o and matrix printer dot o. And then finally when those are ready, make will run Gaussian dot exe. But the important thing is of course, make will not do the last linking first. Make will have to proceed in order which cleans up from the bottom and that it will do properly. We will see later on how to do that once we study graphs a little bit. In another example, you do something smaller. You just update matrix printer dot hpp without changing the signature of the function. Maybe you just make the output look a little prettier or column justify it or something like that. In that case, only matrix printer dot o and Gaussian dot exe will be decompiled in that order. So, let us try out a couple of things with our old make files. We will see a one surprising thing. And last time I was a little sloppy with namespaces. I have since fixed it up. So, here is my make file. Now, anywhere in the make file, you can define variables and use them. For example, you can say hello equal to hello. Now, that variable hello has been defined to be the string. You can also cascade comments. So, what you have to do an action does not need to be exactly one line. You can run multiple comments. You can for example, print the current date and you can echo the message. No one stops you from doing three comments to satisfy this dependency. So, this is a dependency and to refresh that dependency, you have to execute these three comments in sequence. That is the language of make. There has to be a tab here. It is not a space. Make is a very old program and it depends on specific formatting. So, if you replace this tab by anything else, then make does not understand what you are saying. So, let us run this make file. So, if I say make, it claims nothing is to be done. It looked at the dependency structure here, found that all time stamps were exactly as expected. Let me blow this up. By the way, LS dash LTR shows in long format files sorted by modified time. So, as you can see, here are the time stamps and although it is printed only correct to a minute, you can actually get more detailed time stamps by saying stat. So, stat is the statistics about the file color 1 dot exe. It sizes about 21 kilobytes. It takes 48 blocks on disk because of some losses and it says that the last access time of the file is this, last modify time of the file and last change file. What difference between change and modify? I am not up to date on this, but you guys can find out. Anyway, so as you can see, the modify time is the most important thing. So, here is the modify time for color 1 and in fact, all the doto files are older than that. Color 1 dot o is definitely older, but so is matrix printed doto. If you check the stat time, you will find that out. So, now, if I try to make, it says nothing is to be done. So, let us do one thing. Let us just go and touch one of these source matrices. So, if I list it long, you find that I have updated it March 9, 1 30 p m. Now, if I say touch matrix printed dot c p p, all it does is update that last modified time. It does not change the file at all. I touch it and then I l s, now it is 1150. This is 130 a m as of today and this is 1150 as of now. So, now that I have modified matrix printed dot c p p, may doesn't understand that I have not done anything inside the file. It just looks at the time stamp and therefore, now if I done make, it recompiles it and once that is done, it will relink to the exe file. So, this is why it links. Let us say, I told you to print the date. I am going to print the date. Here is the date. It says echo hello, it is echo hello. So, why is this, this is not the correct syntax. You have to put a curly here. Otherwise, you do not look at that variable. So, again I have to touch because, again if I run make now, it will be quite happy with the state of the world. So, if I touch that file again and then I make it now, it compiles again and this time it says echo hello and it echoes hello. So, basically you can declare variables like these and you can use such variables to embed your dash i and dash l flag. So, that you can only define those parts at the beginning of your make file once and then reuse those as variables inside the command lines. Just like I was doing this, you are free to say dash i like so. It is meaningless. So, g plus plus will not check if the directory exists or not. It will just happily take hello. Let us say I said dot dot slash hello. Similar to our example here, I again touch one file to destroy the stability and then I say make. So, again it compiles that file and see what it does is dash i dot dot slash hello. Now, here it says l d cannot open file. So, this is a problem because I am explicitly in the linking phase, I should not be passing dash i arguments. So, let us take off this example and give it in the compilation phase. So, this is a compilation thing. So, I will give it a dash i parameter and I will read on this. So, this will run. So, g plus plus understands if it is doing compiling or linking. So, this time everything goes through fine. So, in the first phase it uses the include path which does not even exist, but then caller one does not ask for that include path anywhere. So, it is fine. Then it compiles the other one, it links print date and equals hello dot dot slash hello. So, that is a summary. You can create things like this. The other thing I wanted to show you is this matter of namespaces and templates. So, remember we had matrix printer dot hpp. Yesterday I showed that we went into using namespace. So, you could say using, but the better practice is to declare whatever you are providing in a namespace. So, remember that boost is a namespace inside which numeric is a namespace, inside which u plus is a namespace. So, you provide those namespaces nested like this and then inside that you say that I am providing a generic class which can print matrices of t's, but I am not changing the namespace. I am declaring the function in the namespace, but then I am closing the namespace in the header file. And how about matrix printer dot cpp that does the same, except it provides an actual implementation. Let me hide this for the moment. Just look at the upper part. The only difference between the header file and this is that this does not have an implementation and this actually has an implementation which just prints the matrix. Now, how am I using it? So, I am using it from caller1 dot cpp and here I use the namespace. That is the right thing to do because if you include the header and the header changes your namespace. Depending on the order in which you include headers, you do not know what namespace is in effect or who takes precedence over who. It is best for dot h for dot hpp files to not change the namespace. You can declare things in a namespace and then the code has to use it in that namespace. Now, let us look at one more thing. Suppose by mistake, so this will work. I have just verified that it works. Caller1 will turn into, let me remove the junk from the namespace. So, this will not work. Why is that? So, I said switch namespace to boost numeric ublas and then do that. Yesterday's worked, by the way. See, it is complaining about something. So, I say make. It is decompiling caller1 dot cpp. It says undefined reference 2 and reading c++ error messages is a huge pain. Why? It says void boost numeric cs1o1 print and inside there is this matrix of doubles is not defined in undefined reference 2. But, hey, I just defined it in, sorry. I just defined it in matrix printer dot hpp. What is the problem? Suppose I do not make it generic. Suppose I just declared a simple print where the input is a matrix of double. So, I comment out the old implementation. I just or maybe just simple print. You just print matrix of doubles and then I have matrix printer dot cpp has to implement it of course. So, let me again comment this one out also. Now, I will implement the non-genetic simple printer and I will do nothing but again do sort of the same thing. It does not matter what I do inside the function. The only thing I change is, it is no longer generic. It is a matrix of doubles. So, now let us try to make it. CS1o1 print is not declared. So, I have to say simple print. So, now it compiled fine, but now it also says undefined reference to boost. So, you see the problem. I mean this is, you would not see the problem. This is actually a bug in C++ and it is not our fault. The issue is this that so we have a situation like this. This is saying I can print and this is trying to call that. The problem is this was first compiled into a dot o file without knowing who is calling. Now, at least in this case I will explain the double case a little later. So, suppose I have this. T is not instantiated with any concrete type. So, if you are compiling this separately, the compiler and linker do not know with what type you will use it. So, it basically does nothing. T can take an infinite number of types. It could be floats, it could be bools, it could be doubles, it could be a vector of floats, it could be a vector of vector of floats, it could be a pair of float and integer, it could be an infinite space of types. So, of course the linker cannot generate code for an infinite possibility of types. So, they generate code for nothing and that is why it is not formed. If you know that caller 1 is going to invoke it on a matrix of doubles, you have to while compiling this fake some code which will make it generate the code for matrix of doubles and that is what those commented lines were doing earlier. So, let me quickly change this. So, here is matrix printer dot cpp. I will remove simple print from here. We will discuss that in the next lecture, what the other case was doing. So, this is just CS 101 print again which can print an arbitrary generic matrix type. Now, what I am going to do is to add this code in matrix printer dot cpp itself. This is fake code. No one uses this code actually. It is a dummy function which prints a matrix of doubles. No one will ever call dummy. You can hide it ever. This just tells the compiler that I will be using this to print matrices of doubles. And now, in matrix here this will be the same except I have to say CS 101. And in matrix printer dot cpp, this was already done. In matrix printer dot hpp, what do I have to do? That does not need to change. I will just uncomment this and get rid of that. So, hpp remains the same except that in the implementation file I have actually made a fake call with the correct type that my customers will use later. If the customer will also use matrix of ints, then you have to declare a second dummy function not in the same. You can do something like matrix int dm etcetera. So, now let us see if this compiles. What is it doing here? dmo has a previous. This is easy. So, this time it compiled fine. Now, let us try the following. So, what is the size of matrix printer dot o? Remember the size carefully, 34 kilo bytes. Now, suppose I do something like CS 101 print dm 2. I will generate a call for int matrices as well. This time if I make it, it will compile fine. I will just define more things. Now, if I list it, look at the size. So, it is included code to deal with int matrices as well. So, when using templates with separate headers and libraries, this is a pen that you have to take. Whatever materialized types the caller will use, you have to artificially materialize them in the implementation, so that for those types you will generate the library code. But, this is still much, much easier than to write this code 5 times over for 5 different types. All you do is materialize the code 5 different times or materialize the call. You do not have to materialize the declaration for 5 different types. So, this is an important thing to take care of. So, for the rest of today, I will discuss the following important issue, which is in several coding exercises, there have been two labs so far, where people have felt that if only we could write nested loops with a number of nestings, which is dependent on an input parameter, then I could solve the problem. It is just that in syntax, I do not know how to declare a nested for loop with a variable number of nestings. So, what do I do? So, for example, so there is earlier lab about finding the largest increasing subsequence in a sequence. There, if for every number in the sequence you created a for loop, where the next index goes from the right of the previous index to the end, then you could solve the problem easily. Yesterday or yeah, Wednesday, there was this problem about decomposing what is called a semi-magic square into a sum of permutation matrix. So, permutation matrix like a n queens board has a one in every row and every column. Now, so one thing is clear that if I gave you a semi-magic square, where every row, every column, no diagonals added up to say C. And by some magic, I could find the permutation matrix P, this is the semi-magic square S. The permutation matrix adds up to exactly one in every row and column. Therefore, the result of this would be, so let us say S 0 would be S 1 with exactly C minus 1 as its rows and columns, sum. Once you take that step, you can repeat it, you can take out another permutation, take out another permutation. So, the basic step you need is taking away one permutation matrix from a semi-magic square. So, what we are looking for is that, so you understand that. And at this point you ask, so can I do this greedily? So, suppose in S 0, the first row has a non-zero in this column. Can I arbitrarily place a one here? So, I will take away one from there. In this row, maybe the, there is a first non-zero is there, so I put a one there. The greedy approach will not work. You should be able to create small 3 by 3 or 4 by 4 examples where by greedily picking the leftmost non-zero column to place a one, you will literally paint yourself into a corner. That later on you will find that you have no choice. You have to place a one here, but there is already a, you have already taken off that column from consideration. So, greedy will not work. Now, what do you do? So, it turns out that this is a long celebrated problem, but you do not need to know the, you know, the difficult part of it. So, it turns out you can do this in polynomial time, but we are not asking for a polynomial time solution. So, suppose I have to exhaustively search for permutation matrices, so that I can take off one. It should be somewhat intuitively clear that as long as I give you a semi-magic square, there should exist a permutation which you can take off. That is not too difficult to see. The difficulty in finding that permutation matrix and greedy looking for it will not help. So, in terms of doing an exhaustive search, which is not too exhaustive. So, how will you go about? Clearly, the non-zero structure of S will matter if the first row has non-zero in these columns. I have to keep track of where I placed a 1. If that does not work out in the end, I have to come back and change. So, suppose this matrix is n by n. If only I could declare a piece of code which says for I 1 equal to 0 through n minus 1. And here I say if S of I 0, sorry I 0. If S 0 I 0 is equal to 0, then continue. If the 0th row and I 0th column is 0, then I cannot place a permutation 1 there. So, I will just continue. Now, I want to write something like for I 1 equal to 0 through n minus 1, except I 0. Again, here I want to write if S of 1 I 1 is equal to 0, then continue. So, that explores the space of I 1's. Then is a for I 2 etcetera. You nest like this in the code at level n. You basically say, if I have found a configuration of I 1 I 0 through I n minus 1, then that is a permutation matrix and I can take it out. Everyone ok with this? And then you close all those n loops. This will come up again and again. Let me give you another example. So, suppose I tell you that the input to your code is the number n and your job is to not use recursion, which you have not learnt anywhere. You have to print all n factorial permutations of the number say 0 through n minus 1 and you cannot use recursion. So, in particular if I say n equal to 3, if I input 3, then you have to print 0 1 2. I am not printing it in the correct order, but anyway 0 2 1 and so on up to 2 1 0. So, I have to output 6 lines. How to do that? Without using recursion. It is always good to think recursively and then if necessary you can implement it without recursion or if you do not think there will be a performance you can implement it with recursion. So, why is it possible to arrange n things in n factorial ways? Well, the first thing can only go in one way. The second thing can go in two ways. Once you have two things, the third thing can be inserted in three ways. That is the reason why. So, suppose I give you a list of indices. So, I say that I am going to put all these in a vector. The first thing can be placed only in one way and therefore, the way index can only be 0. The second thing can go either to the left or the right. The second thing has two possible values. We will call them 0 and 1. The third thing can go in three positions. So, it can have values 0 1 2. So, again those are like the I 0 through I n minus 1. If I give you a list I 0 through I n minus 1, where I 0 can have value only 0, I 1 can have value 0 or 1, I 2 can have value 0 1 2. I give you this vector. It should be now easy to write out a permutation. Is that correct? So, again given this structure, I can write out a nested loop with a variable number of nestings. So, I should be able to write for I 0 equal to 0 only, 0 to 0 or I 1 equal to 0 to 1 or I 2 equal to 0 to 2 etcetera. Here, I would say print permutation I 0 through I n minus 1 and I will close those for you. How do you write print permutation? Well, you can write in a multiple ways. There may be smarter ways and not the smart ways, but it is basically the way of placing these things. So, how do you go about it? The very 0 th element is placed somewhere. There is only one way to do that. Now, you read I 1 and if I 1 is 0, then you place the second element to the left, otherwise to the right. In general, you have placed J minus 1 element so far. So, there are J gaps. The next guy can have some value, put it in the correct gap. So, print perm is no big deal. You can do it. The somewhat bigger deal is how do you implement this nesting with n levels? How do you implement this nesting with n levels? Where n is an input? So, instead of dealing with this somewhat difficult problems, so what I was looking for in the lab is if you go up to the point where you say, I want to implement this arbitrary nesting where I look for positions where I can put once, but I cannot implement it. You will get most of the credit. You will get 80 percent or more. If you have actually cracked the problem and done an exhaustive search routine, you will get full marks. If you have taken a graduate course in algorithms, then you might know the best algorithm to do it. The best algorithm for the permutation matrix problem can be done in time, which is the number of non-zeros in the input matrix times the row sum, any row sum or any column. In fact, you can do it in log of row sum. That is the best algorithm, but that is an involved algorithm. Now, let us look at how to write nested for loops like this. We will take a very simple example to keep the treatment in a classroom friendly. Suppose I want to write down all numbers with a given radix and with a certain number of digits. We have already seen that in binary, if I define the radix to be 2 and let us say I have 3 digits, then how many combinations we have? 8. What are the actual numbers? 0, 0, 0, 0, 0, 0, 1, 1, 1. Suppose I say radix is equal to 3 and end digits is equal to say 3. Now, how many different combinations are there? 3 to the power 3, so 27 possible numbers. The first number is again 0, 0, 0, then it is 0, 0, 1, then it is 0, 0, 2 and then it is 0, 1, 0, which is equal to 3 in radix 3. Then it is 0, 1, 1, 1, 2, now what? 2, 0. So, this is again a situation where you would like to write a loop of the form for digit 0 equal to 0 to radix minus 1 for digit 1 equal to 0 to minus 1. In fact, the other way around, this would be slowest changing. So, this would be n minus 1. So, this is n minus 1, n minus 2 and so on. And then finally, for digit 0, the least significant digit equal to 0 through radix minus 1 print. So, again I have n nested loops. If this n is part of the input, then it is a little difficult to see how to do this. But it is actually not so difficult. If you looked at that pattern, what was I doing? I was always attacking the least significant incrementable digit. If that failed, I did a carry over, overflow and carry over. So, let us see how to implement that. So, this should be fairly simple, even if the original problems are not that simple. So, here it goes. A and the printing thing. I will print from the unit plus onwards just for simplicity. So, suppose I pass in number of digits 5 and radix 3. It does not matter, you can give any input. I will create a vector of integers digits, initially all zeros. Now, the semantics of digits is that digits 0 is the least significant digit in the opposite order. And now, in an infinite loop, I will first print digits. So, these digits are basically some shallow gate for the loop indices stored in a vector. I cannot really write down n nested loops for loops. Instead, I declare a vector where I store all the indices of the for loops. And then, I try to find the change point for int change equal to 0 from the lowest significant place to n digits. If the digits that change is less than radix minus 1, then I can still increment it. If it has become radix minus 1, then I cannot do anything more. If I find a digit that can be increased, I increase it. I record the success. And then, for all lower digits, I set them to 0. And then, if I change anything, I can break the outer for loop. If I could not change anything, then I break the outer for loop. I go out of the outer for loop. Here, I break the inner for loop. I do not need to look for any more places to change. I only need to change at one place and correct the lower significant bits behind that. So, how many people are comfortable with what this code is doing? So, look for the least significant digit that you can increase. Zero out things that are even lower significant than that and proceed. So, it is not surprising that this will work fine. So, I think I have already compiled it. So, with 5 digits and radix 3, first is all 0s. Then, I increase to 1, 2, 0, 1. Then, it is 1, 1. Then, it is 2, 1. Then, it is 0, 2 and so on. At the end, I get all 2s. That is the last number. So, and how many are there? There should be 3 to the power 5. You can do that by what is called a word count. How many lines? 243 lines, which is what you would expect. So, what is the moral of the story? The moral of the story is this guy faked what you would write somewhat more easily as a variable number of nested for loops. The loop indices went into this vector called digits. And the general strategy is there is a bunch of indices. I want to change them in a clock, you know, like a digital clock like order. There are faster changing digits and slower changing digits. Try to find the fastest changing or least significant digit that you can clock up. Increase that by 1 and then 0 out all the other guys. So, now this code should give you an idea about how to hunt for a permutation matrix to subtract. So, instead of digits, what will I have? I will have columns. There will be a vector of int called columns, where the index will be the row rx and columns rx will give you at what column in row rx you want to put a 1 in the permutation matrix that you have subtract. And so, if you think of what is going on here, focus inside the for loop only inside here. See, there is this outside world which has somehow found the current state of digits. And I am supposed to go to the next state. So, how am I going to do that? Can I write the permutation? What will be the, I will not finish it up now, but let me try to just write down the code structure. You can try to finish it offline. So, instead of digits, I will just have say const int however many things you are trying to permute say equal to 4. And here I will have the insertion position. That is what the permutation index works. So, it is pause of n and 0. In fact, by our default convention, when you say all 0s in case of permutation, it will be first insert 0, then insert 1 to the left of it, insert 2 to the left. So, the very first permutation will print is n minus 1 to 0 in the opposite order. And the last one you will print will be 0 through n minus 1. So, now, this is the main loop which will print out permutations. So, this will be print perm on pause which we have not written yet. And now, did change will remain. So, what will happen here? If digits change, so n digits will be just n objects, pause digits. Pause change can go from what to what? There is no radix now. If change is 0, then I can only be 0. So, this has to be change itself. So, see I 0 can only go from 0 to 0. So, change is this index. Change runs from 0 to n minus 1. So, therefore, you say that if the position, so if change is equal to 0, then position change has to be less than change itself, not minus 1. Then I can increase the position and I change this. And the rest will be the same. I will reset all the others to 0. Let me just print out what this does without printing the permutation. You can do the permutation printing offline. That is easy to do. This is the same. Let us see if this works. I will comment out the print form which you have not written yet. Instead, I will just print what else digits. Now, let us look at this carefully with 4 things. So, 0, the first guy will always be 0. Second was 0 and 1. Then this one clocked up to 1. This is 0 and 1. This can go up to 2. This can go up to 3. And how many entries do I have? 24 for 4 things. So, I am just putting a 1 to 1 correspondence between a permutation and a 4 tuple of numbers. And I am clocking up the numbers in a way from which I can map directly into a permutation. So, anytime you have to explore a space which is controlled by a bunch of nested indices, hunting for columns in rows so that you can make a permutation matrix, looking for positions which constitute an increasing subsequence, printing permutations of things. Anytime you are faced with this, instead of trying to write nested for loops with a variable number of nestings, you make up a vector which stores the state of the indices in those nested loops. And then modify it like this. Attack the innermost loop with changes that can still be increased. And then things which are even inner than that, you reset to its starting value. So, we will discuss this in more detail either offline or in the next lecture.