As the world is moving towards faster and reliable technologies, the trend of computing is turning towards parallel processing. High-performance computers are increasingly in demand in the advanced human civilization. Parallel processing has emerged as a key enabling technology in modern computers. For exploitation of parallelism, a theoretical treatment is needed. For this, we have designed a tool that will analyze a ‘C’ program theoretically, given in input by the user, to calculate maximum available parallelism in the program. The tool processes the ‘C’ program, taken in input and collects the information regarding various types of dependencies i.e. data dependency, control dependency, existing among the instructions. Using this information, tool calculates the maximum achievable parallelism in the execution of the input program. But as we know that the achievable parallelism is always minimum value from software parallelism and hardware parallelism. So the tool also displays the achievable parallelism with given number of PE’s (Available Hardware Parallelism).


CHAPTER - 1 Introduction
To design a tool that will analyze a source program, written in ‘C’ language, taken as input, for various type of dependencies (i.e. data dependency, control dependency) existing among the statements of the source program and on the basis of these results the program will suggest the optimal parallel machine with identical Processing Elements ( with enough number of circuits to carry out operation in a single statement) and will also calculate the degree of parallelism that can be archived for the input ‘C’ program with the limited number of identical Processing Elements available.

Source File

Analysis of Source File to calculate achievable concurrency in the Source Program using our Tool

Practical Implementation of implicit parallelism

PE 1

PE 2

PE 3

PE n

Fig 1.1


In the detailed sense, we can say that the tool will take a source file (say source.c) in the input and the input file must be written in ‘C’ Language. The file “source.c” will be analyzed by our tool (mainpro.c) for following dependencies : • • • • Anti Dependency Flow Dependency Output Dependency Control Dependency

On the basis of information, generated from this analysis, the our tool will provide number of levels and in each level all the statements can run concurrently.


CHAPTER - 2 Related Concepts
2.1 Parallelism
Parallelism is an efficient form of information processing which emphasizes the exploitation of concurrent events in the computing process. There are two types of parallelism• • Implicit Parallelism Explicit Parallelism

Implicit Parallelism An implicit approach uses a conventional language such as C, Fortran, Lisp, or Pascal to write the source program. The sequentially coded source program is transliterated into parallel object code by a parallelizing compiler and this compiler must be able to detect parallelism and assign target machine resources. With parallelism being implicit , success relies heavily on the intelligence of a parallelizing compiler. This approach requires less efforts on the part of the programmer.

programmer Execution by runtime system Source code Written in sequential language Fig – 2.1 Implicit Parallelism Explicit Parallelism The second approach requires more efforts by the programmer to develop a source program using parallel dialects Parallelizing of C, FORTRAN, Lisp, or Pascal. Parallelism Compiler is explicitly specified in the user programs. This will significantly reduce the burden on the compiler to detect parallelism. Instead the compiler needs to preserve parallelism and , where possible, assigns target machine resources. Parallel Object Code programmer Concurrent Object Code

Source Code written in Concurrent Dialects of C,FORTRAN, Lisp, or Pascal Execution by runtime system 4 Concurrency preserving Compiler

Fig 2.2 – Explicit Parallelism

The different statements in a program may be dependent on each other in various ways. After analyzing these various dependencies between different statements we can seek the possibility for concurrent execution of instruction of same program.

2.2 Conditions of Parallelism
Various types of dependencies which may exist among the statements are as followsData Dependency The ordering relationship between statements is indicated by the data dependence. There are five types of data dependence1. Flow Dependence : A statement S2 is flow dependent on statement S1 If an execution path exists from S1 to S2 and if at least one output (variableassigned) of S1 feeds in as input (operand to be used) to S2.

2. Antidependence : A statement S2 is antidependent on statement S1 if the S2 follows S1 in program order and if the output of S2 overlaps the input to S1.

3. Output Dependence : Two statement are output dependent if they produce (write) the same output variable.

4. I/O Dependence : Read and Write are I/O statement. I/O dependence occurs not because the same variable is involved but because same file is referenced by both I/O statements.

Unknown Dependence : The dependence relation between two statements can not be determined in the following situations:


• • • •

The subscript of a variable is itself subscribed(Indirect Addressing) The subscript is non linear in the loop index variable. The subscript does not contain the loop index variable. A variable ap3pears more than once with subscripts having different coefficients of the loop variable.

When one or more of these conditions exists, a conservative assumption is to claim unknown dependence among the statements involved.

Control Dependence Control dependence refers to the situation where the order of execution of statements can not be determined before run time. For example Conditional statement in FORTRAN (IF in Fortran) will not be resolved until run time. Different paths taken after a conditional branch may introduce or eliminate data dependence among instructions. Dependence may also exist between operations performed in successive iterations of a looping procedure. The successive iterations of the following loop are control independentDO 20 I = 1,N A(I) = C(I) IF (A(I) .LT. 0) A(I)=1 Continue

Following loop has control dependent iterationsDO 10 I = 1,N IF (A(I-1) .EQ. 0) A(I)=0 Continue

Control Dependence often prohibits parallelism from being exploited. Compiler techniques are needed to get around the control dependence in order to exploit more parallelism.

Resource Dependence This is different from data or control dependence, which demands the independence of the work to be done. Resource Dependence is concerned with the 6

conflicts in using shared resources, such as integer units, floating-points units, register, and memory areas, among parallel events. When the conflicting resource is ALU, we call it ALU dependence. If the conflicts involve workplace storage, we call it storage dependence. In the case of storage dependence, each task must work on independent storage locations or use protected access to shared writable data. The transformation of a sequentially coded program into a parallel executable form can be done manually by the programmer using explicit parallelism, or by a compiler detecting implicit parallelism automatically. I n both the approach, the decomposition is the primary objective. Program partitioning determines whether a given program can be partitioned or split into pieces that can execute in parallel or a follow a certain prespecified order of execution. Some programs are inherently sequential in nature and thus can not be decomposed into parallel branches. The detection of parallelism in programs requires a check of various dependence relations. Bernstein’s Conditions In 1966, Bernstein revealed a set of conditions based on which two processes can execute in parallel. A process is a software entity corresponding to the abstraction of a program fragment defined at various processing levels. We define the input set Ii of a process Pi as the set of all input variables needed to execute the process. Similarly, the output set Oi consists of all output variables generated after execution of the process Pi. Input variables are essentially operands which can be fetched from the memory or registers, and output variables are the results to be stored in working registers or memory locations. Now consider two processes P 1 and P2 with their input set I1 and I2 and output set O1 and O2. respectively. These two processes can execute in parallel if the are independent and do not create confusing results. Formally these conditions are stated as follows-

I1 I2 O1

∩ ∩ ∩

O2 O1 O2

= = =

ф ф ф

These three equations are known as Bernstein’s conditions. The input set I i is also called the read set or the domain set of P i. Similarly, the output set Oi has been called the write set or the range of process Pi. In terms of data dependence, Bernstein’s conditions simply imply that two processes can execute in parallel if they are flow-independent, antiindependent and output-independent.


CHAPTER – 3 Analysis
In the analysis phase of Software Development Life Cycle (SDLC), we analyze every module of the software separately corresponding to the requirements to be fulfilled. In our project, the requirement is to implement a tool to recognize and represent the parallel processable statements in a ‘C’ program and for the fulfillment of the requirement the tool is modularized into three different modules, as follows 1. Data dependency module 2. Control dependency module 3. Parallel Processable Statements Recognition Module Optimization for limited number of identical processing elements (with enough number of circuits to carry out operations in a single statement) is also carried out there. In data dependency checking we are further dividing it into three modules as 1. Flow dependency module 2. Anti dependency module 3. Output dependency module

3.1 Data Dependency Module
In the data dependency module, the source file is scanned by our project program and two spare files are generated. One of them contains the source file statements with each statements preceded by statement numbers as S1, S2, S3..up to 8

end of file. This file is named as “statement file”. Another file generated is named as “token file” which contains all the tokens( identifiers, keywords etc.) along with the occurrence of that token whether it is in the right or left side of the assignment sign. By default it takes the left occurrence for the tokens for example in the statement #include<stdio.h> the “include” will be considered with the occurrence left. Apart from it, for every token, the statement number in witch its occurrence is noticed is also printed in the token file. Besides of these three type of information, every token is associated with a integer value that is used for the analysis of control dependency in a loop.

Source File (Preprocessed)

Scannin g

Statement no. File

Token File

Data Dependency Testing

Data Dependency Graph


3.1.1 Flow dependency Module
Statement No. File Token File

Flow Dependency Test 9

Flow Dependency Information

Flow Dependency Graph Fig – 3.2 DFD for FLOW DEPENDENCY MODULE

3.1.2 Anti Dependency
In the Anti Dependence Module, the project simply uses the files generated during the scanning of the source file named statement file and token file for deciding that whether a Anti dependency exists between two statements or not. The algorithm for Anti dependency, uses the information for every token whether its occurrence is in the left or in the right. And based upon this information the anti dependence between the statements is calculated.

Statement No. File

Token File

Anti Dependency Test

Anti Dependency Information

Anti Dependency Graph



3.1.3 Output Dependency
In the Output Dependency Module, similar to flow dependence and antidependence modules, the files generated during the scanning process of the source program ( Statement File, Token File) are used for output dependency analysis between the different statements of source file. The algorithm for Output Dependency check is described in the implementation section of the report. For the output dependency check, the algorithm simply analyze the tokens written in Token File and their corresponding occurrence.

Statement No. File

Token File

Output Dependency Test

Output Dependency Information

Output Dependency Graph



3.2 Control Dependency Module
Control Dependence is defined only for loops. Hence the Control Dependency Module is concerns only with loops ( for, while etc. ) . The algorithm for Control Dependence is described in implementation section of the report. Control Dependence declares a loop as dependent if the iterations of the loop can not get executed in parallel to each other and the loop is declared as independent when all the iterations of the loop can be executed in concurrently. The Control Dependence Algorithm uses the files Statement File and Token File to decide a loop’s control dependence.

Statement no. File

Token File

Control Dependency Testing

Displays Loop’s Dependence



3.3 Parallel Processable Statements Recognition Module
In the Parallel Processable Statements Recognition Module, all the results generated during the Flow Dependency Module, Antidependeny Module, Output Dependency Module and Control Dependency Module are used to generate a graph which shows the execution sequence for the source program statements with maximum possible concurrency among them. This graph is named as “Concurrency Graph” in the project. The module also takes input for available PE’s from user and rearrange the graph which shows the maximum achievable parallelism with the given number of PE’s for the user’s program.

Statement no. File

DD Graph

Calculate Parallel Processable Statements

Concurrency Graph


Rearrange (According to number of PE’s)


Rearranged Graph


CHAPTER – 4 Design
In the design phase of System Development Life Cycle (SDLC), the relationship among different modules of the system and the way in which they interact to each other is considered. For our project, the different modules and interaction among them is shown in following two different flow charts.

Source file

Preprocessing (File without comments) st.c and out.c

Lexical Analysis

st.c & out.c

Data Dependency Test

Data Dependency Graph

st.c & out.c

Control Dependency Test

Statement Number with Dependency info

St.c & DD Graph

Concurrency Test

Concurrency graph

Concurrency Graph

Rearranging According to number of PE’s 14

Rearranged Graph

Fig – 4.1

And the second flow chart is as shown below


‘C’ Source File

Preprocessing (Source file without comments)

Lexical Analysis

Token File (out.c) Statement File (st.c)

Checking Dependencies among variables (Data & Control Depend.)

Graph Plotting Data Dependencies (Antidependency, Flow & Output) Shows Control Dependency with Statement number of loops

a 15


Checking Dependencies and finding the statements that can run concurrently

Graph Showing Different level of statements and in each level statements can run concurrently

Arranging the order of the statements that can run concurrently according to the number of processing elements available

Rearranged Graph According to the given set of processing elements


Fig - 4.2


CHAPTER – 5 Implementation
In the implementation phase of System Development Life Cycle (SDLC), all the flowcharts & DFD are implemented on the machine by writing the code using suitable programming language. Thus, in the implementation phase, computer programs are coded for each & every module, described in Analysis Phase. For implementing the modules, we use following Data Structures primarily-

1. 2. 3. 4.

FILE * fpi - This file pointer for input source file. FILE * fpo - This file pointer for token file (“out.c”). FILE * fps - This file pointer for Statement number flie (“st.c”). static int fd[50] - This 1-D integer array is used for Flow dependency information. 5. static int od[50] - This 1-D integer array is used for Output dependency information. 6. static int ad[50] - This 1-D integer array is used for Anti dependency information. 7. int iv[50] - This 1-D integer array is used for Isolated (Independent) node information. 8. nod node - This object of nod structure is used for drawing nodes in data dependency graph. 9. var v[100] - v is array of structure used for storing identifiers and constants . in “out.c”. 10. char cdarr[20][20] - This 2D character array is used for storing the control dependent information for particular loop. 11. int j - This integer variable is used for storing the statement number in input source file. 17

12. int scount - scount is used for time information for sequential processing. 13. int pcount - pcount is used for time information for parallel processing. 14. int npcount - npcount is used for time information for parallel processing when number of processing element are given. 15. static int ll[20][20] - The function depend() uses ll 2D array to store dependent statement number w.r.t. particular statement number. 16. static int lev[20][20] - The function level() uses lev[20][20] 2D array to store number of level with statement numbers that can run concurrently. 17. int ** lev1 - The function element() uses lev1 2D pointer to store number of level that can run concurrently with statement numbers according to available processing elements. 18. int npe - npe is number of processing elements for optimal processing.

19. typedef struct p { char vari[10]; char occr; int st; }var; Structure for various identifiers and constants used in source file with their occurrence and statement number output in file “OUT.C”. char vari[10 ] char occur int st - identifier name - occurrence of identifier. - statement number of identifier.

20. typedef struct q { char lab; int xx; int yy; }nod;


Structure for drawing nodes associated with labels in data dependency graph. char lab - label of nod. int xx - X- dimensional value on the screen for the node. int yy - Y- dimensional value on the screen for the node.

Function description –
FUNCTION PROTOTYPE void displayfile(char *) Data Structure used - file that has to be opened Step 1 - Open file where name is received in the argument Step 2 - Read a character in X. Step 3 - check if X is not EOF , go to Step 4 else go to Step 5. Step 4 - Display character on screen , Read next character in X and go to Step 3. Step 5 Exit .

FUNCTION PROTOTYPE void removecomment(char *) Data Structure used - file to be used , s (character from file ) Step 1 - open file received in argument. Step 2 - read first character from file . Step 3 - repeat until end of file (a) if (s== ‘/’) read next character if (s== ‘/’) skip upto next line character


if (s==’*’) skip upto next ‘/’ character [End of Loop] Step 4 - Exit

FUNCTION PROTOTYPE void ad_graph() Data Structure used - ad[] Step 1 - Set pointer to the initial element of ad[]. Step 2 - while pointer is not pointing to the null value (a) Take two elements (pairwise ) from the pointer Position. (b) Draw nodes with the corresponding labels and show Dependency between them (c ) Increase pointer by two. [End of While] Step 3 - Exit.

FUNCTION PROTOTYPE void od_graph() Data Structure used - od[] Step 1 - Set pointer to the initial element of od[]. Step 2 - while pointer is not pointing to the null value (a) Take two elements (pairwise ) from the pointer Position. (b) Draw nodes with the corresponding labels and show Dependency between them


(c) Increase pointer by two. [End of While] Step 3 - Exit.

FUNCTION PROTOTYPE void fd_graph() Data Structure used - fd[] Step 1 - Set pointer to the initial element of fd[]. Step 2 - while pointer is not pointing to the null value (a) Take two elements (pairwise ) from the pointer Position. (b) Draw nodes with the corresponding labels and show Dependency between them (c) Increase pointer by two. [End of While] Step 3 - Exit.

FUNCTION PROTOTYPE iso_nodes() Data Structure used - iv[], j Step 1 - Repeat until i<j if the value of iv[i]=7 Draw node with label i. [End of Loop] Step 2 - Exit


FUNCTION PROTOTYPE void dependency_graph() Data Structure used - fd[ ],ad[ ],od[ ] Using function fd_graph( ), od_graph( ), ad_graph( ) and iso_graph( ) drawing all the dependencies simultaneously. FUNCTION PROTOTYPE void depend ( ) Data Structure used - ll[] [], ad[], od[] , fd [] Using Arrays od[] (output Depenency array ) , fd[] ( flow Depenency array ) , ad[] (anti dependency array ) , making an Array whose rows shows the statements that are dependent On the statement with the row number.

FUNCTION PROTOTYPE void level( ) Data Structure used - lev[ ][ ],ll[ ][ ] Step 1 - Start with statement number 1 as the current statement And level 1 as the current level , with statement 1. Step 2 - Repeat step 3 until no more statement remains. Step 3 - Check the statements one by one that are not dependent to the current level . If you find such statements add them to the current Level and check the next statement with the current Level, Else Increase the current level by 1 and add the next Unmatched statement in it. [End of Loop]


Step 4 - Exit .

FUNCTION PROTOTYPE void costcalc() Data Structure used - lev[] , lev1[], scount,pcount,npcount (a) Count all non zero elements of lev[] calculating Sequential cost. (b) Count all the rows whose first element is nonzero calculating minimum cost(pcount). (c) Count all the number of rows whose first element is nonzero, in lev1[] calculating minimum cost with limited Processing Elements.

FUNCTION PROTOTYPE void controldepend() Data Structure used - v[] Step 1 - Get the start and end point for a loop. Step 2 - Check all the statements in the block for antidependancy Step 3 - If any two statements are dependent Declare the loop control Dependent and exit. Step 4 - Check all the statement , if any statement has the same


Variable in both sides of assignments , declare the loop Control dependent else declare independent.

CHAPTER – 6 Testing & Debugging
Token File generated by taking input file ( without comment) and after scanning the file it generates the token file “out.c”. This file have identifiers, occurrence of identifiers and statement number. It also generates separate statements numbers for loops ( i.e. for loop ,while loop ) and IF statement for control dependency. Wrong Output - Problem with the Token file is for statement like “a=b/d;” because “/” is used for identifying comment from source file the function generate identifiers “a” and “bd”. This problem was basically from comment removing function (removecomment( )) . vari a bd c a c for a1 0 a1 10 occr stm L R L R R L L R L L 1 1 2 2 2 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0

Correct Output - In the correct output file identifiers “b” and “d” are shown below. vari occr stm 24

a b d c a c for a1 0 a1 10


1 1 1 2 2 2 3 3 3 3 3

0 0 0 0 0 0 0 0 0 0 0

Problems in Statement File – This file is obtained from source input file by removing the comments and assigninig the statement numbers to each and every statement in the format s1,s2,s3….. For this particular execution we have taken the input file named “t.c” which is transformed into “st.c” as the statement file by the program. The input file’s contents are – a=b/d; // Testing Program c=a+c; for(a1=0;a1<10;a1++) { a=b+c; sc=cs; } while() { d++; w=q; s=c+a; } c=a+c;

For the above shown input file, Our program generate the corresponding statement file named “st.c” whose contents are – a=b/d; c=a+c; for(a1=0;a1<10;a1++) { a=b+c; sc=cs; 25

} while() { d++; w=q; s=c+a; } c=a+c; We got Blank line in place of comment and our program was taking the blank line as a statement and was assigning this a statement number. Wrong Output No statements __ ___________ s1 a=b/d; s2 c=a+c; s3 s4 for(a1=0;a1<10;a1++) s4 { s4 a=b+c; s4 sc=cs; s4 } s5 while() s5 { s5 d++; s5 w=q; s5 s=c+a; s5 } s6 c=a+c; s7

Correct Output No statements __ ___________ s1 a=b/d; s2 c=a+c; s3 for(a1=0;a1<10;a1++) s3 { s3 a=b+c; s3 sc=cs; s3 } s4 while() s4 { s4 d++;


s4 s4 s4 s5

w=q; s=c+a; } c=a+c;

Data Dependency Graph – Data dependency check function takes statement number file and token file as input and gives data dependency information, Data dependency graph is drawn by this information by dependeny_graph() function. Output Obtained - Data Dependency Graph shows multiple arcs between two nodes (nodes represents statement number in graph) if same data dependency between two statements.

Fig 6.1


Expected Output - Data Dependency Graph should show single arcs between two nodes (nodes represents statement in graph) if same data dependency between two statements ,but due to loops there may be many same type of dependencies , and handling this problem was somewhat complex.

Control Dependency - Control dependency function takes statement number file and token file as input and gives output whether the loops are control dependent or control Independent. A loop is considered as one statement, this function outputs as follows.. Wrong Output Statement no 4 Statement no 0 Control Dependent Control Independent

Wrong output was due to associativity of sprintf() function that is Right to Left. This wrong output was corrected by consideration of associativity. Correct Output Statement no 3 Statement no 4 Control Dependent Control Independent


CHAPTER – 7 Results

1. Welcome Screen for Project 2. Input
source file name

3. Main Menu of the Project (Press “Down Arrow” for menu)


Fig 7.1 4. Display Source code file (Press “space” for this output)


Fig 7.2

5. Data Dependency Graph for the input source file


Fig 7.3

6. Separate Output Dependency Graph, Anti Dependency and Flow Dependency Graph (Press “up arrow for these Graphs)

6.1 Output Dependency Graph (Press “o” for this Graph)


Fig 7.4

6.2 Anti Dependency Graph (Press “a” for this Graph)


Fig 7.5

6.3 Flow Dependency Graph (Press “f” for this Graph)


Fig 7.6

7. Optimization Graph (Press “Right Arrow” for this Graph)


Fig 7.7


Rearrange Graph according to the number of Processing element available (Press “p” for this Graph)


Fig 7.8


Control Dependency (Press “c” to check whether loops are control dependent )


Fig 7.9

9. Statement number file generated by Source file (Press “s” for display this file)

Fig 7.10

CHAPTER – 8 Limitation & Enhancement


1. The Input program must be error free (i.e. syntax error, semantic error etc.). The input program has assumed to be completely error free. As the project is analyzing the program before compilation phase and programs written by user are error prone so to get the assumption true is difficult. “goto” statement is not considered in the program analysis by project i.e. the input program must be free from “goto” statements. The project is not considering the change in the flow of control due to “goto” statement which may cause a lot of change in the dependence among various statements. Hence a program with “goto” statements may be analyzed by our project in a wrong way and the results may not as expected one. Function Calls are not considered by our project i.e the input program must not contain any function call otherwise the project will not take in to account the control transfer to the called function and the function call statement will be analyzed by project as a simple statement. Project will analyze the function call statement and proceed to the statement following this function call in the code instead of analyzing the statements of called function’s definition. The project can not deal with pointers as the project is making only static checks. The project is not dealing with Input-Output Dependence. Hence the file operation statements (opening and closing the file ) can not be handled. Resource Dependence is also ignored in the project analysis so the conflicts created due to simultaneous access of shared resources can not be cop with. Unknown Dependencies are not taken in to account by our project. The Project is taking input as the number of identical Processing Elements (Having same number of Adders , Multipliers etc. ). It is not taking into account to the PE’s having different number of adder, multiplier etc. circuits.



4. 5. 6. 7. 8.

1. This project can be enhanced to take into considerations Function Calls and “goto” statements etc.


2. Analysis for Input-Output Dependence can be added to the project separately so the Input – Output operation (File operations, Printer Operations etc.) can be handled by the project. 3 Project can be further enhanced to take into account the asymmetric PE’s (having different number of adders, multipliers etc.).

4. The project can be enabled to break the source program into different concurrently executable fragments that can be assigned to different processors to get executed concurrently. 5. The project can be made to be capable of assigning the parallel executable fragments to different processors and also collect that the result generated from different processors and combine that result to display as output to user. 6. The project can be enabled to calculate overheads incurring in assigning the fragments to different processors and collecting the results from them.

CHAPTER - 9 Conclusion

Finally, we can summarize that the tool developed in the project analyzes the source program written in ‘C’ language for various types of dependencies ( flow dependency, antidependency, output dependency and control dependency). Tool generates the information regarding various type of dependencies among the statements in the input ‘C’ program and using that information, the tool recognizes parallel processable statements in the input ‘C’ program. All the parallel processable statements are represented by a concurrency graph by project. This information can be used further in dividing the input program into concurrently executable fragments that can be assigned to different processors running in parallel. Thus, program written in sequential machine can be transported to a parallel machine with the help of our project.

CHAPTER – 10 Bibliography


1. Kai Hwang, “Advanced Computer Architecture”, McGraw-Hill, New York, 1993. 2. Kai Hwang & Faye A. Briggs, “Computer Architecture and Parallel Processing”, McGraw-Hill, New York, 1984. 3. Gonzalez, M.J., and Ramamoothy, C.V., “Recognition & Representation of Parallel Processable Streams in Computer Programs” , in parallel processor systems, Technologies and Applications, Macmillan Ltd., London, England, 1970. 4. G.Goff, K. Kennedy, and C. W. Tseng, “Practical Dependence Testing”, Proc. ACM SIGPLAN Conf. Prog. Lang. Design and Implematation, 1991. 5. Robert Lafore, “Object-Oriented Programming in C++”.


Sign up to vote on this title
UsefulNot useful