|| Author: Cyberdude || Back to articles ||
[*] Title = Calculator's Mathematics Problems Resolution [*] Author = Giuseppe aka Cyberdude [*] Mailto = viromarquantebello[at]libero[dot]it =[ M e n ù ]= [0x0] A simple C code to arousing your curiosity [0x1] The rapresentation of numbers in a finished space [0x2] Two problems with addition operation [0x3] The smooler positiv number considerable and the rapresentable it [0x4] Binary unfinished rapresentations [0x5] Polinomy sovling with Horner [0x6] Linear systems resolution [0x7] Gauss's elimination of unknown variables to obtain a triangulate upper matrix [ 0x0 - A simple C code to arousing your curiosity ] Hi to all boys... I want start this text arousing your curiosity with a simple C code... what is the output of this code?? I think that it is very "funny" --------[Cod.c]-------------------------------------------------------------------------------------------- int main() { double a=0,b=0; printf("[***] Initial value of double [a]--> %f\n",a); printf("[***] Initial value of double [b]--> %f\n\n",b); printf("[**] I run two same while cicle for [a] and [b] now!!\n\n"); while(a<1.0) a+=0.25; while(b<1.0) b+=0.1; printf("[*] Final value of [a]\n\tIn the cicle I added 0.25 to it\n\t--> %f\n\n",a); printf("[*] Final value of [b]\n\tIn the cicle I added 0.1 to it\n\t--> %f\n\n",b); return 0; } --------[Cod.c]-------------------------------------------------------------------------------------------- --------[Cod.s]-------------------------------------------------------------------------------------------- /* This is the asm version of the prev C code Compile it using => gcc Cod.s Run it using = > ./a.out */ msgtxt1: .string "[***] Initial value of double [a]--> %f\n" msgtxt2: .string "[***] Initial value of double [b]--> %f\n\n" msgtxt3: .string "[**] I run two same while cicle for [a] and [b] now!!\n\n" msgtxt4: .string "[*] Final value of [a]\n\tIn the cicle I added 0.25 to it\n\t--> %f\n\n" msgtxt5: .string "[*] Final value of [b]\n\tIn the cicle I added 0.1 to it\n\t--> %f\n\n" value025: .long 0 .long 1070596096 value01: .long -1717986918 .long 1069128089 .globl main main: pushl %ebp /* I push the ebp register to preserve the information */ movl %esp, %ebp /* Move %esp in %ebp this is a default operation used to */ subl $40, %esp /* preserve the stack! After I alloc 40 byte of memory */ /* To work with 32-bit 64-bit or 80-bit values I use the Floating Point Unit (FPU). The first value in the top of FPU register is named ST0 or ST, the second ST1 etc. */ fldz /* Is a asm diclaration of a double value 0.0 */ fstl -16(%ebp) /* In the st0 is stored 0.0 I copy it in -16(%ebp) */ fstl -8(%ebp) /* I copy the same value 0.0 in -8(%ebp) */ fstl 4(%esp) /* I copy the value 0.0 in the 4(%eps) */ movl $msgtxt1, (%esp) /* I move the msgtxt1 in %esp to call the printf syscall */ call printf /* I call the printf syscall */ fstpl 4(%esp) /* I copy the value 0.0 in the 4(%esp) and pop the stack of FPU */ /* So now in the top it is anymore 0.0 value but the second value stored next it */ movl $msgtxt2, (%esp) /* I move the msgtxt2 in %esp to call the printf syscall */ call printf /* I call the printf syscall */ pushl $msgtxt3 /* I push the msgtxt3 in the stack to call the puts syscall */ call puts /* I call the puts syscall */ jmp ControlCicle1 add025: fldl -16(%ebp) /* I push the value stored in -16(%ebp) in the top of FPU stack */ fldl value025 /* Now push the value 0.25 in the top and the first pushed value become the second value after the top */ faddp %st, %st(1) /* Now I do the top value (0.25) + the second value! After I pop the stack becouse the sum is stored in the destination position (%st1). So I want that the result of this sum is on the top of stack */ fstpl -16(%ebp) /* Now I pop the stack and store the sum in -16(%ebp) to refresh his value */ ControlCicle1: fldl -16(%ebp) /* I push the value stored in -16(%ebp) in the FPU stack! this value in the first time was 0.0 but I refresh it during the execution of this code */ fld1 /* Now I push the value 1.0 so st0 is 1.0 and st1 is the value stored in -16(%ebp) */ fucompp /* Now I can compare the value stored in st0 and in st1 */ fnstsw %ax /* I must store the result of this comparation in a 16bit register as %ax */ sahf /* To use this value I must move the value stored in %ax in the flag register becouse I don't have a direct access to %ax */ ja add025 /* If the first value is bigger than the second I jump to add025 */ jmp ControlCicle2 /* Else if the value stored in -16(%ebp) (the second value in FPU stack) is > 1 I jump to the next cicle labeled ControlCicle2 */ add01: /* add01 is similar to add025 but I sum 0.1 and not 0.25 */ fldl -8(%ebp) fldl value01 faddp %st, %st(1) fstpl -8(%ebp) ControlCicle2: /* ControlCicle2 is similar to ControlCicle1 but I jump to the */ fldl -8(%ebp) /* add01 block code and not to add025 block code */ fld1 fucompp fnstsw %ax sahf ja add01 fldl -16(%ebp) /* Now I push in FPU register the value stored in -16(%ebp)*/ fstpl 4(%esp) /* and pop the FPU register to move this value in 4(%esp)*/ movl $msgtxt4,(%esp) /* after that I move the msgtxt4 in the top of esp stack*/ call printf /* And I call printf syscall */ fldl -8(%ebp) /* I do the same of the prev block of code with the value */ fstpl 4(%esp) /* stored in -8(%ebp) */ movl $msgtxt5, (%esp) call printf movl $0, %eax /* I kill the process and exit*/ leave ret --------[Cod.s]-------------------------------------------------------------------------------------------- the prev code creat 2 double named a and b. In the first time boot have value zero! I print this value ... in the second time i creat two while cicle! boot the cicles ended when the value of the double variables become >1.0! in the first while cicle I added 0.25 value to a in the second i added 0.1 to b. We think that the final value of a and b is 1. 0!! it's true? but strangely the result of the second cicle is different!! Why?? What do you think if I said you that this different result is a cause of dead for 25 soldiers?? I answer to this question in the second time! We must know only a little theory part first! [ 0x1 - The rapresentation of numbers in a finished space ] Ok start the theory part! we must know that the calculator assign a finished space to rapresents a single number! so we can rapresents only the 'n' number that are rapresentable with a number of values smooler of the space permitted! If we try to rapresents a biggest number of permettid it we cause overflow! The number that we consider in this text are the real number! this type of number is compost of one base, one mantissa and one caracteristic. For exemple we can rapresent the number 123 as 123 * 10^0 or 12,3 * 10^1 or 1,23 * 10^2 etc... 123 is the mantissa, 10 is the base and ^1 ^2 ^3 are the caracteristics. If I want rapresent a number with caracteristic biggest of the permitted it the calculator trunk our number or it make round the number. The calculator consider all number in normal form! the normal form is that the first value to the right of point. For exemple the number 123.715 in normal form is 0.123715 * 10^3! the number 0.000713 in normal form is 0.713 * 10^-3 [ 0x2 - Two problems with addition operation ] The sum operation is very simple when the caracteristic is the same for exemple : 0.2841 * 10^-3 + 0.4212 * 10^-3 = 0.7053 * 10^-3 For the moment we can imagine that our calcolator permit we to use only 4 values after the point! this is only an exemple to work with simple number and understend the concept! Ok if we consider only 4 values for the decimal part we can have an exemple of trunk operatione committed from the calculator! If I wan do this addition : 0.2831 * 10^-3 + 0.8112 * 10^-3 I can becouse the caracteristic are the same but the result is this : 1.0953 * 10^-3 that it isn't in normal form, so the calculator must transform this form in normal form in this way : I must move all values of one position direction right and add 1 to the caracteristic! the result is : 0.1095 * 10^-2 now the number is rapresentated in normal form but its value is changed becouse the 4° value is trunked!! In reality the calculator supports more value for the decimale part, but is not unifinished and if we want rapresent a number with a decimal part biggest of permitted it the calculator trunk our number. Another problem born when we want add two number with different caracteristic! for exemple 0.2841 * 10^-3 + 0.4813 * 10^-2!! In this case I must equals the caracteristic... I transform 0.2841 * 10^-3 in 0.0284 * 10^-2 and execute the addition operation : 0.0284 + 0.4813 = 0.5097 * 10^-2 in this case I have lose only a little information value of the my numbers! But if I must operate this addition : 0.2841 * 10^-3 + 0.1248 * 10^-7 and transform the more little caracteristic (-7) in -3 the number 0.1248 * 10^-7 become this number: 0.00001248 * 10^-3 and if we imagine that we have only 4 values for decimal part... this value is 0.0000 * 10^-3 that is 0! The computer consider this value 0 and the result of this sum operation is 0.2841 * 10^-3 that is the value of the first number!!! This is an important error that we must consider!! --------[Sum.c]-------------------------------------------------------------------------------------------- #include <math.h> int main() { system("clear"); double a = 1/pow(10,4); double b1 = 0.2841; double b2 = 0.1248; printf("\tIn this exemple we imagine the max values that I can use for decimal part is 4 \n\n"); printf("[*] The values of b1 and b2 are:\n\t[b1] => %.4f *10^-3\n\t[b2] => %.4f *10^-7\n\n",b1,b2); printf("[*] Now I must transform b2 from 10^-7 to 10^-3 to do the addition from the two values\n"); b2 = b2 *a; printf("\t[*] The new value of [b2] is %.8f *10^-3 but we use only %.4f *10^-3\n",b2,b2); printf("\t[*] Now I do [b1]+[b2]\n"); double b3 = b1+b2; printf("\t[*] The result of this addition is [b3] = %.8f ",b3); printf("but I use only 4 values for decimal part so [b1]+[b2] = %.4f\n",b3); printf("\t\t[b1]+[b2] == [b1] <<- the value of [b2] is not considerated\n"); return 0; } --------[Sum.c]-------------------------------------------------------------------------------------------- --------[Sum.s]-------------------------------------------------------------------------------------------- clear: .string "clear" msg1: .string "\t In this exemple we imagine that the max values that I can use for decimal part is 4 \n" msg2: .string "[*] The values of b1 and b2 are:\n\t[b1] => %.4f *10^-3\n\t[b2] => %.4f *10^-7\n\n" msg3: .string "[*] Now I must transform b2 from 10^-7 to 10^-3 to do the addition from the two values\n" msg4: .string "\t[*] The new value of [b2] is %.8f *10^-3 but we use only %.4f *10^-3\n" msg5: .string "\t[*] Now I do [b1]+[b2]\n" msg6: .string "\t[*] The result of this addition is [b3] = %.8f " msg7: .string "but I use only 4 values for decimal part so [b1]+[b2] = %.4f\n" msg8: .string "\t\t[b1]+[b2] == [b1] <<- the value of [b2] is not considerated\n" pow10e4:.long -350469331 .long 1058682594 val2841: .long -1003304360 .long 1070739121 val1248: .long -1903529506 .long 1069544164 .globl main main: pushl %ebp /* Push the ebp to preserve the information */ movl %esp, %ebp subl $56, %esp /* Alloc 56byte of memory*/ movl $clear, (%esp) /* Clear the screen */ call system fldl pow10e4 /* Push the value 1/10^4 rapresentated with label pow10e4 */ fstpl -32(%ebp) /* And move it in -32(%ebp)*/ fldl val2841 /* The same for 0.2841*/ fstpl -24(%ebp) fldl val1248 /* And 0.1248*/ fstpl -16(%ebp) movl $msg1, (%esp) /* Print the msg1 */ call puts fldl -16(%ebp) /* Move the value 0.2841 and 0.1248 in esp register */ fstpl 12(%esp) /* and print the msg2*/ fldl -24(%ebp) fstpl 4(%esp) movl $msg2, (%esp) call printf movl $msg3, (%esp) /* print the msg3 */ call printf fldl -16(%ebp) /* push 0.1248 in FPU register and multiply it */ fmull -32(%ebp) /* to 1/10^4*/ fstpl -16(%ebp) /* store the result of multiplication in -16(%ebp) */ fldl -16(%ebp) /* repush the refreshed value of 0.1248 */ fstpl 12(%esp) /* And pop the FPU register and push the result in 12(%esp) */ fldl -16(%ebp) /* Repush the same value in 4(%esp) becouse I must print */ fstpl 4(%esp) /* it two time in the msg 4*/ movl $msg4, (%esp) /* Print the msg4*/ call printf movl $msg5, (%esp) /* Print the msg5 */ call printf fldl -24(%ebp) /* Push 0.2841 in FPU */ faddl -16(%ebp) /* And add it to 0.1248 */ fstpl -8(%ebp) /* Pop the result from the FPU register and move it in -8(%ebp)*/ fldl -8(%ebp) /* Push this value and repop it in 4(%esp)*/ fstpl 4(%esp) movl $msg6, (%esp) /* Print the msg6*/ call printf fldl -8(%ebp) /* Take the value that I have stored in -(%ebp) */ fstpl 4(%esp) /* And move in in 4(%esp)*/ movl $msg7, (%esp) /* Print the msg7 */ call printf movl $msg8, (%esp) /* Print the msg8 */ call printf movl $0, %eax /* Exit */ leave ret --------[Sum.s]-------------------------------------------------------------------------------------------- We must think that the machine operation are different from the reality!! a+(b+c) is different from (a+b)+c and a * (b+c) is different from (a*b)+(a*c) and (a*b)/b is different from a!! For exemple imagine three variable a,b,c all rapresentated in normal form in our calcolator that take we only 8 values for rapresents the decimal part!! [*] a = 0.23371258 * 10^-4; [*] b = 0.33678429 * 10^2; [*] c = -0.33677811 * 10^2 If I resolve the addirion a+(b+c) I do this operation: [1] b+c = 0.00000618 * 10^2 that in normal form is 0.61800000 * 10^-3 [2] a + 0.61800000 * 10^-3 [3] a = 0.02337125 * 10^-3 [4] 0.02337125 + 0.61800000 = 0.64137125 * 10^-3 Buf if I resolve the same addition in this way (a+b)+c the result is different: [1] a+b = 0.00000023 * 10^2 + 0.33678429 * 10^2 = 0.33678452 * 10^2 [2] 0.33678452 - 0.33677811 = 0.00000641 * 10^2 that in normal form is 0.64100000 * 10^-3 NOTE: a+(b+c) is 0.64137125 * 10^-3 (a+b)+c is 0.64100000 * 10^-3 in the second way I have lose 5 values of information! Is more correct to do the operation with the same caracteristic first and the different later to preserv more information!! [ 0x3 - The smooler positiv number considerable and the rapresentable it ] Now I can describe to you the machine' s propriety of precision that we named ESP. With this we want rapresent the smooler positiv number that the calculator "consider" int the sum with 1! simply if I do 1+a where a is a number >0 but <ESP the calculator interpret a as 0 and the result of sum is 1! If I want know what is the smooler positiv number that my calculator consider different from zero I can run this code --------[Esp.c]-------------------------------------------------------------------------------------------- int main() { system("clear"); system("clear"); printf("[*] FIND THE ESP VALUE OF THIS CALCULATOR\n"); double esp = 1; while((1+esp)!=1) { printf("%.70f\n",esp); esp/=2; } esp*=2; printf("[*] The min positiv value that the calculator consider != 0 is\n\t==> %.70f\n",esp); printf("[*] If I use the next min positive value after it for my calculator this value is 0\n"); } --------[Esp.c]-------------------------------------------------------------------------------------------- --------[Esp.s]-------------------------------------------------------------------------------------------- clear: .string "clear" msg1: .string "[*] FIND THE ESP VALUE OF THIS CALCULATOR" msg2: .string "[*] The min positiv value that the calculator consider != 0 is\n\t==> %.70f\n" msg3: .string "[*] If I use the next min positive value after it for my calculator this value is 0\n" p70: .string "%.70f\n" val2: .long 0 .long 1073741824 .globl main main: pushl %ebp /* I preserve the information */ movl %esp, %ebp subl $40, %esp /* And alloc 40bytes of memory*/ movl $clear, (%esp) /* Clear the screen */ call system movl $clear, (%esp) call system movl $msg1, (%esp) /* And print the msg1*/ call puts fld1 /* Push the 1.0 value in FPU register */ fstpl -8(%ebp) /* Pop it and store in -8(%ebp) */ jmp control /* Jump to control cicle*/ execute: fldl -8(%ebp) /* Push the value stored in -8(%ebp) in FPU*/ fstpl 4(%esp) /* Pop it in 4(%esp)*/ movl $p70, (%esp) /* push the p70 string in esp */ call printf /* And print the value stored in -8(%ebp)*/ fldl -8(%ebp) /* Push this value in FPU */ fldl val2 /* Push the value 2.0 in FPU*/ fdivrp %st, %st(1) /* I do the division between st1/st0 and pop st0 */ fstpl -8(%ebp) /* I pop the result in -8(%ebp) and refresh the prev value of it*/ control: fldl -8(%ebp) /* Push the value stored in -8(%ebp) in FPU*/ fld1 /* Push the value 1.0 */ fadd %st, %st(1) /* Add 1.0 to value stored in -8(%ebp) */ fxch %st(1) /* change the position of st0 and st1*/ fucompp /* compare st0 and st1 */ fnstsw %ax /* move the result of compare in %ax*/ sahf /* and write it in the flag register */ jne execute /* if st0 and st1 are different jump to execute */ fldl -8(%ebp) /* Else push the value stored in -8(%ebp) in FPU*/ fadd %st(0), %st /* And add it with itself */ fstpl -8(%ebp) /* Refresh the value of -8(%ebp) */ fldl -8(%ebp) /* Repush it in FPU register */ fstpl 4(%esp) /* And pop it in 4(%esp) */ movl $msg2, (%esp) /* Move the msg2 in (%esp) */ call printf /* Call printf syscall to print it*/ movl $msg3, (%esp) /* Move the msg3 in (%esp) */ call printf /* Call printf syscall to print it */ movl $0, (%esp) /* Exit procedure*/ call exit --------[Esp.s]-------------------------------------------------------------------------------------------- The esp value is the smooler positiv number that the calculator consider different from zero but we can rapresent several value < esp in the calculato. We can rapresent but the calculator consider they as zero If we want know the smooler value < esp that we can rapresent on our calculator we can run this code --------[Min.c]-------------------------------------------------------------------------------------------- int main() { system("clear"); double min = 1; double temp; while(min!=0) { temp = min; min/=10; } printf("[*] The min rapresentable number of my compuer is:\n-> %.1100f\n\n",temp); printf("[*] I can't rapresent a number more small of this!!\n"); exit(0); } --------[Min.c]-------------------------------------------------------------------------------------------- --------[Min.s]-------------------------------------------------------------------------------------------- clear: .string "clear" msg1: .string "[*] The min rapresentable number of my compuer is:\n-> %.1100f\n\n" msg2: .string "[*] I can't rapresent a number more small of this!!\n" val10: .long 0 .long 1076101120 .globl main main: pushl %ebp /* I preserve the information pushing %ebp */ movl %esp, %ebp subl $40, %esp /* And alloc 40bytes of memory */ movl $clear, (%esp) /* I clear the screen */ call system fld1 /* Push the value 1.0 in the FPU register */ fstpl -16(%ebp) /* And pop it in -16(%ebp) */ jmp control /* Jump to the control label */ execute: fldl -16(%ebp) /* I push the value of -16(%ebp) in FPU */ fstpl -8(%ebp) /* And pop it in -8(%ebp) (my temp variable) */ fldl -16(%ebp) /* Repush the value of -16(%ebp) in FPU */ fldl val10 /* And Push the value 10.0 in FPU */ fdivrp %st, %st(1) /* Divide the value of -16(%ebp)/10 */ fstpl -16(%ebp) /* And pops the result in -16(%ebp) */ control: fldl -16(%ebp) /* I push the value -16(%epb) in FPU */ fldz /* I puth the value 0.0 in FPU */ fxch %st(1) /* Change the value in st1 with st0 */ fucompp /* Compare st0 with st1 */ fnstsw %ax /* Move the result in %ax */ sahf /* And store it in flag register */ jne execute /* If this value are different I jump to execute*/ fldl -8(%ebp) /* The value stored in -8(%ebp) is the last value of my element first to become equals to zero*/ fstpl 4(%esp) /* I pop it in 4(%esp) */ movl $msg1, (%esp) /* Push the msg1 in esp */ call printf /* And print it*/ movl $msg2, (%esp) /* Push the msg2 in esp*/ call printf /* and print it*/ movl $0, (%esp) /* Exit procedure*/ call exit --------[Min.s]-------------------------------------------------------------------------------------------- [ 0x4 - Binary unfinished rapresentations ] A considerable problem is that for several decimal number are necessary unfinished binary bit!! If we want store a number that is rapresentated by unfinished binary bin in 24 byte... the number that we store is not the number that we want store!! For exemple: if I want rapresent the decimale 0.25 in binary the conversion is very simple: -> 0.25 * 2 = 0.50 => store the 0 and use the 50 to continue the conversion -> 0.50 * 2 = 1.00 => store the 1 and continue but with 00 I can't continue The final value of 0.25 in binary is 01 The broblem born when I want convert 0.1 decimal value in binary!! [point1] -> 0.1 * 2 = 0.2 => store the 0 and use .2 to continue [point2] -> 0.2 * 2 = 0.4 => store the 0 and use .4 to continue [point3] -> 0.4 * 2 = 0.8 => store the 0 and use .8 to continue [point4] -> 0.8 * 2 = 1.6 => store the 1 and use .6 to continue [point5] -> 0.6 * 2 = 1.2 => store the 1 and use .2 to continue [point6] -> 0.2 is the same of point 2!!! This is an unifinished cicle!!!! The final value of 0.1 in binary is 0 0011 0011 0011 0011 0011 0011 0011 ... when I write 0.1 (decimal value) in 24 byte I can store only 24 byte so: 0.1 = 0.00011001100110011001100 In this way I have introduct an error of 0.00000000000000000000000110011001100.... that in decimal is equale to 0.000000095!! --------[Bin.c]-------------------------------------------------------------------------------------------- int main() { double a = 0.25; printf("BIN VALUE OF 0.25 = "); while(a!=0) { a*=2; printf("%.0f",a); if(a>=1) a-=1; } double b = 0.1; int count = 0; printf("\nBIN VALUE OF 0.1 = "); while(b!=0 && count != 1000) { b*=2; printf("%d",(int)b); if(b>=1) b-=1; count++; } printf("...\n"); exit(0); } --------[Bin.c]-------------------------------------------------------------------------------------------- On February 25, 1991, during the Gulf war this "little" problem killing 28 soldiers and injuring around 100 other people... if you are interested to it you can read the article of professor Douglas N. Arnold (University of Minnesota) at this link: http://www.ima.umn.edu/~arnold/disasters/patriot.html [ 0x5 - Polinomy sovling with Horner ] First to continue I want said only several things: all the operations in the calculator are solved as poly becouse they are trunked pow! When we "transform" the unfinished sum in finished sum we creat a little errors that we can consider becouse we can know it! Now we can imagine that our calculator must solve the next operation : a3*x^3 + a2*x^2 +a1*x^1+a0 there are several mode to solve it! for exemple we can solve it in this way: [P1]= a3 * x * x * x [P2]= a2 * x * x [P3]= a3 * x [P4]= P1+P2+P3+a0 If we consider this in general : (an * x^n) + [a(n-1) * x^(n-1)] + ... + a1 * x^1 + a0 and we solve this operation in the same way thet we have solved the first we obtain this resolution: (n+(n-1)+...+1)M = {[n(n+1)]/2} * M that is the (Sum form i = 1 to n) * i = n(n+1)/2 But this is not a good mode to solve it! The best mode is using the Horner Algorithm! a3*x^3 + a2*x^2 +a1*x^1+a0 = ((a3*x+a2)x+a1)x+a0 in this way we evidence the x value so we have this operations [P1]= a3*x [P2]= P1+a2 [P3]= P2*x [P4]= P3+a1 [P5]= P4*x [P6]= P5+a0 The result is the same but now we can compare the "work" that do the calculator in this two ways to know the best way to resolve!! In the first case we do 6 multiplications and 3 additions; in the second we do 3 additions and 3 multiplications! So the Horner Algorithm is more "economic" for machine! --------[Hor.c]-------------------------------------------------------------------------------------------- int main() { system("clear"); printf("[We want solve this poly with Horner Algorithm]\n"); printf("\t[poly] = a3*x^3 + a2*x^2 + a1*x^1 +a0\n"); printf("\nImagine that :\n"); printf("\t[a3] = 2\t[a2] = 4\n\t[a1] = 6\t[a0] = 8\n\t[x] = 2\n"); printf("So we must solve this : 2*2^3 +4*2^2+6*2^1+8\n"); printf("\nHornet solve it in this way: ((2*2)+4)*2+6)*2+8\n"); int a[] = {8,6,4,2}; int x = 2; int temp = a[3]; int i; for(i=2; i>=0; i--) { printf("\t=> (%d*%d)+%d = ",temp,x,a[i]); temp = (temp*x) + a[i]; printf("%d\n",temp); } printf("\n==> The result is %d\n",temp); exit(0); } --------[Hor.c]-------------------------------------------------------------------------------------------- --------[Hor.s]-------------------------------------------------------------------------------------------- clear: .string "clear" msg1: .string "[We want solve this poly with Horner Algorithm]" msg2: .string "\t[poly] = a3*x^3 + a2*x^2 + a1*x^1 +a0" msg3: .string "\nImagine that :" msg4: .string "\t[a3] = 2\t[a2] = 4\n\t[a1] = 6\t[a0] = 8\n\t[x] = 2" msg5: .string "So we must solve this : 2*2^3 +4*2^2+6*2^1+8" msg6: .string "\nHornet solve it in this way: ((2*2)+4)*2+6)*2+8" msg7: .string "\t=> (%d*%d)+%d = " msg8: .string "%d\n" msg9: .string "\n==> The result is %d\n" .globl main main: pushl %ebp /* Push the ebp register in the stack to preserve the */ movl %esp, %ebp /* information and after that alloc 56Byte of memory */ subl $56, %esp /* to execute my operations! */ clearScreen: movl $clear, (%esp) /* clear the screen */ call system printStrings: pushl $msg1 /* push the ms1 and puts it to the output */ call puts pushl $msg2 /* the same for msg2 */ call puts pushl $msg3 /* the same for msgs3*/ call puts pushl $msg4 /* the same for msg4 */ call puts pushl $msg5 /* the same for msg5 */ call puts pushl $msg6 /* the same for msg6 */ call puts storeValueInMemory: movl $8, -28(%ebp) /* In -28(%ebp) I store the value 8 (a[0])*/ movl $6, -24(%ebp) /* In -24(%ebp) I store the value 6 (a[1])*/ movl $4, -20(%ebp) /* In -20(%ebp) I store the value 4 (a[2])*/ movl $2, -16(%ebp) /* In -16(%ebp) I store the value 2 (a[3])*/ movl $2, -12(%ebp) /* In -12(%ebp) I store the value 2 (x) */ assignTemp: movl -16(%ebp), %eax /* I store the value of a[3] in -8(%ebp) */ movl %eax, -8(%ebp) /* My temp variable*/ createCount: movl $2, -4(%ebp) /* I store the value 2 in -4(%ebp) I use it as counter*/ jmp control /* jump to control label*/ execute: movl -4(%ebp), %eax /* I store the value of counter in %eax */ movl -28(%ebp,%eax,4), %eax /* I stay in -28(%ebp) take the value in %eax and */ movl %eax, 12(%esp) /* multiply it to 4 after from -28(%ebp) add the */ /* value obetenute from 4*(value in %eax) and obtain a*/ /* new registry address: ex %eax = 2 => 4*2 = 8 */ /* -28+8 = -20%ebp I move the value stored in -20(%ebp) */ /* in %eax in this case is a[2] = 4! I do it to obtain a[i] */ movl -12(%ebp), %eax /* Move the value of x in 8(%esp) */ movl %eax, 8(%esp) movl -8(%ebp), %eax /* Move the value of temp variable in 4(%esp)*/ movl %eax, 4(%esp) movl $msg7, (%esp) /* Move the msg7 string in (%esp) and print it*/ call printf copyTemp: movl -8(%ebp), %eax /* Remember the temp value in %edx */ movl %eax, %edx mulOperation: imull -12(%ebp), %edx /* Multiply the value of x to temp the result is in %edx */ movl -4(%ebp), %eax /* The same procedure of first to obtain a[i] */ movl -28(%ebp,%eax,4), %eax addOperation: addl %edx,%eax /* After add the value of a[i] to the result of multiply */ movl %eax, -8(%ebp) /* refresh the value of temp */ printTemp: movl -8(%ebp), %eax /* Move the value of temp in 4(%esp)*/ movl %eax, 4(%esp) movl $msg8, (%esp) /* Move the string msg8 in (%esp)*/ call printf /* print it*/ decrementCounter: leal -4(%ebp), %eax /* take a pointer to counter */ subl $1, (%eax) /* and decrement it value of 1 */ control: cmpl $0, -4(%ebp) /* Compare my counter stored in -4(%ebp) to 0 value */ jns execute /* If the counter is >= 0 jump execute */ printResult: movl -8(%ebp), %eax /* I move my temp variable in 4(%esp) becouse I must */ movl %eax, 4(%esp) /* print it*/ movl $msg9, (%esp) /* Move the msg9 string in esp */ call printf /* and print the string+value of temp*/ quit: movl $0, (%esp) /* Exit procedure*/ call exit --------[Hor.s]-------------------------------------------------------------------------------------------- If we want valutate this algorithm we must consider the complessity of time to solve the operations When we considere this type of operations the must expensive is the multipication! We can consider the time of this algorithm in this way : In every cicle iteration we do 1 multiply and 1 addition! We do n iterations (from n-1 to 0 included)!! So we do n multiply and n addition to resolve a poly of dimension n T(N) = N multiply = O(N) and this is the best time that we can implement in our calculator to solve the poly operation! [ 0x6 - Linear systems resolution ] To analize the linera systems we must consider the different matrix type! In the first time we must know that there are 2 type of matrix : the full matrix and the spread matrix in witch there are several null elements. If the null elements in spread matrix are organized in a particular way we can distinguish two particular matrix: [*] triangulate upper matrix ---- ---- ---- ---- | 10 | 21 | 13 | 15 | ---- ---- ---- ---- | 00 | 33 | 92 | 02 | ---- ---- ---- ---- | 00 | 00 | 88 | 12 | ---- ---- ---- ---- | 00 | 00 | 00 | 61 | ---- ---- ---- ---- [*] triangulate lower matrix ---- ---- ---- ---- | 10 | 00 | 00 | 00 | ---- ---- ---- ---- | 21 | 33 | 00 | 00 | ---- ---- ---- ---- | 13 | 92 | 88 | 00 | ---- ---- ---- ---- | 15 | 02 | 12 | 61 | ---- ---- ---- ---- When we want resolve a system the calculator interpeter it as a matrix : 2x + 5y = -8 6x - 7y = 20 ----- ----- ----- | +2x | -5y | -08 | ----- ----- ----- | +6x | -7y | +20 | ----- ----- ----- We can resolve it with Cramer method: to obtain x we consider the 2x2 matrix in with the x colums is rapresentated of known column divided the unknown 2x2 matrix ----- ----- | -08 | +05 | ----- ----- | +20 | -07 | (-8)(-7) - (20)(5) 56 - 100 -44 x = --------------- = ------------------ = ---------- = ---- = 1 | +02 | +05 | (2)(-7) - (6)(5) -14 -30 -44 ----- ----- | +06 | -07 | ----- ----- to obtain y we do the same of for x ----- ----- | +02 | -08 | ----- ----- | +06 | +20 | 40 + 48 +88 y = -------------- = --------- = ----- = -2 | +02 | +05 | -14 -30 -44 ----- ----- | +06 | -07 | ----- ----- but using Cramer to execute 21*19*20! multiply the calculator necessity of 10^4 centurys so we must find another type of resolution! We can use Gauss! In this text we analize only nxn matrix! (2x2 3x3 4x4 ecc...) Imagine that we must resolve the triangulate upper matrix : 2(x1) + 2(x2) + 4(x3) = 5 0(x1) - 7(x2) - 11(x3) = -8 0(x1) + 0(x2) + 2(x3) = 2 we can use the back sostitution to resolve it starting from 2(x3) = 1 so x3 = 1 -7(x2) = -8+11(x3) => x2 = -3\7 2(x1) = 5 -2(x2) -4(x3) => x1 = 13\14 The same for the tiangulate lower matrix: 2(x1) + 0(x2) + 0(x3) = 4 3(x1) + 2(x2) + 0(x3) = 5 1(x1) + 2(x2) - 3(x3) = 1 so we take x1 = 2 and obtain x2 = -1\2 x3 = 0 in general the lower tiangulate matrix named L: l11(x1)+........................... = b1 l21(x1)+l22(x2)+................... = b2 ln1(x1)+ln2(x2)+ln3(x3)+...+lnn(xn) = bn so: x1 = b1\l11 x2 = [b2 - l21(x1)]\l22 ... xn = {bn - [Sum form i=1 to n-1 of(ln(i)*x(i))]} / l(n,n) the resolution of an upper triangulate matrix named U is: x(n) = b(n)\u(n,n) x(i) = {b(i) - [Sum from k = i+1 to n of(u(i,k) x(k)]} / u(i,i) --------[bks.c]-------------------------------------------------------------------------------------------- #include <math.h> int main() { int matrix[3][3]; double b[3]; matrix[0][0] = 2; matrix[0][1] = 2; matrix[0][2] = 4; b[0] = 5; matrix[1][0] = 0; matrix[1][1] = -7; matrix[1][2] = -11; b[1] = -8; matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 2; b[2]= 2; int i,k,j; double sum; system("clear"); printf("Soving of 3x3 matrix polinomy with BackSolution alghoritm!\n"); printf("The poly as matrix:\n"); printf("\n[ x1 ][ x2 ][ x3 ] [ B ]\n"); for(i=0;i!=3;i++) { for(k=0;k!=3;k++) { printf("[%4d]",matrix[i][k]); } printf(" = [%3.0f]",b[i]); printf("\n"); } for(i=2; i>=0; i--) { sum = 0; for(k=i+1;k!=3;k++) { sum = sum + (matrix[i][k]*b[k]); } b[i] = (b[i]-sum)/matrix[i][i]; } printf("\nThe solutions: \n"); for(j=1;j!=4;j++) { printf("x[%d] = %f\n",j,b[j-1]); } } --------[bks.c]-------------------------------------------------------------------------------------------- --------[bks.s]-------------------------------------------------------------------------------------------- clear: .string "clear" msg1: .string "Soving of 3x3 matrix polinomy with BackSolution alghoritm!" msg2: .string "The poly as matrix:" msg3: .string "\n[ x1 ][ x2 ][ x3 ] [ B ]" msg4: .string "\nThe solutions: \n" print4d: .string "[%4d]" print30f: .string " = [%3.0f]" printdf: .string "x[%d] = %f\n" slashn: .string "\n" val5: .long 0 .long 1075052544 valm8: .long 0 .long -1071644672 val2: .long 0 .long 1073741824 .globl main main: pushl %ebp movl %esp, %ebp subl $100, %esp movl $2, -64(%ebp) /* I creat the 3x3 upper triangulate matrix */ movl $2, -60(%ebp) /* That rapresents my poly */ movl $4, -56(%ebp) /* We can imagine the matrix stored in this way */ movl $0, -52(%ebp) /* | -64(%ebp) | -60(%ebp) | -56(%ebp) |*/ movl $-7, -48(%ebp) /* | -52(%ebp) | -48(%ebp) | -44(%ebp) |*/ movl $-11, -44(%ebp) /* | -40(%ebp) | -36(%ebp) | -32(%ebp) |*/ movl $0, -40(%ebp) movl $0, -36(%ebp) movl $2, -32(%ebp) fldl val5 /* I creat the column of known terms pushing */ fstpl -88(%ebp) /* the double values 5 -8 and 2 in FPU register */ fldl valm8 /* And repopping they in ebp register so we have: */ fstpl -80(%ebp) /* | -88(%ebp) |*/ fldl val2 /* | -80(%ebp) |*/ fstpl -72(%ebp) /* | -72(%ebp) |*/ movl $clear, (%esp) /* I clear the screen */ call system movl $msg1, (%esp) /* And puts msg1 msg2 and msg3 in output*/ call puts movl $msg2, (%esp) call puts movl $msg3, (%esp) call puts movl $0, -28(%ebp) /* In -28(%ebp) store a counter = 0 */ jmp PrintControlRow /* And jump to the PrintControlRow label*/ PrintInRow: movl $0, -24(%ebp) /* Create another counter = 0 in -24(%ebp) */ jmp PrintControlCol /* And jump to PrintControlCol to know if I must print another column of this row */ continuePrint: movl -28(%ebp), %edx /* Move the counter stored in -28(%ebp) in %edx*/ movl -24(%ebp), %ecx /* And the counter stored in -24(%ebp) in %ecx */ movl %edx, %eax /* Calcule the address of the next value of matrix */ addl %eax, %eax /* that I must print! I take the value of edx. For exemple */ addl %edx, %eax /* if edx = 1 I know that I stay in the second row becouse */ addl %ecx, %eax /* the first is in 0.Since is a 3x3 matrix I must sum the value */ /* of counter 3 times to go to the end of the first row! So I do */ /* %eax+%eax+%edx so I sum it with the value the %ecx counter */ /* (the value of the counter of colum) */ movl -64(%ebp,%eax,4), %eax /* When I have calcolate the moving from the first index of matrix -64(%ebp) */ /* I can sum to this address 4byte*number of movings to take the */ /* exactly value row/column that I must print in this moment! */ movl %eax, 4(%esp) /* So I print it */ movl $print4d, (%esp) call printf leal -24(%ebp), %eax /* After I take the column counter stored in -24(%ebp) */ addl $1, (%eax) /* and increment it to continue! */ PrintControlCol: cmpl $3, -24(%ebp) /* Control if the counter in -24(%ebp) is = 3 */ jne continuePrint /* If is different I jump to continuePrint */ movl -28(%ebp), %eax /* If I stay here is becouse I have finished to print a row */ fldl -88(%ebp,%eax,8) /* So now I must print the known value of this row. So I */ fstpl 4(%esp) /* go in -88(%ebp) and moving %eax(number of row)*8Byte */ movl $print30f, (%esp) /* To know how known value I must print! I move this value */ call printf /* in 4(%esp) and print it!*/ movl $slashn, (%esp) /* print the string slashn*/ call printf leal -28(%ebp), %eax /* And incremente the row counter!*/ addl $1, (%eax) PrintControlRow: cmpl $3, -28(%ebp) /* Control if the counter stored in -28(%ebp) is = 3*/ jne PrintInRow /* if is different from 0 i jump to PrintInRow label*/ ResetCounterTo2: movl $2, -28(%ebp) /* If I stay here is becouse I have finished to print matrix */ jmp CalculateControlRow /* So I set the counter stored in -28(%ebp) to 2 and jump */ ResetSumAndColCount: fldz /* I push the value 0.0 in FPU register*/ fstpl -16(%ebp) /* and store it in -16(%ebp) this is a variable named Sum */ movl -28(%ebp), %eax /* After that I move the row counter in %eax */ addl $1, %eax /* And incremente it to 1*/ movl %eax, -24(%ebp) /* After I move this value in -24(%ebp) to set column counter (remember that is a triangoular matrix so if I stay in the row 2 I know that the value stored in column 1 is = 0 */ jmp CalculateControlCol /* After jump to CalculateControlCol:*/ calculateSum: movl -28(%ebp), %edx /* I move the row counter in %edx */ movl -24(%ebp), %ecx /* and the column counter in %ecx */ movl %edx, %eax /* So I can calulate the exactly cell that */ addl %eax, %eax /* I must use in this time in the same way that */ addl %edx, %eax /* I do first to find the cell to print */ addl %ecx, %eax movl -64(%ebp,%eax,4), %eax /* When I have found it i push this value */ pushl %eax /* in (%esp)*/ fildl (%esp) /* And read a double value of it of 64bit*/ leal 4(%esp), %esp movl -24(%ebp), %eax /* Now I move the column counter in %eax*/ fldl -88(%ebp,%eax,8) /* multiply it for 8byte and sum to the -88(%ebp) address */ fmulp %st, %st(1) /* Multiply %st (the known value) with %st1 (matrix cell) */ /* the result stay in %st1 but I pop %st so now the result */ /* is in %st1*/ fldl -16(%ebp) /* Push in FPU the value of variable Sum created first */ faddp %st, %st(1) /* this value now stay in %st, the prev %st (the resutl of the sum) go in %st1 and I sum it to %st, after pop the %st so now in the %st there is the result of the addition operation */ fstpl -16(%ebp) /* Now I move this value in -16(%ebp) to refresh it */ leal -24(%ebp), %eax /* After that incremente the column counter of 1 */ addl $1, (%eax) CalculateControlCol: cmpl $3, -24(%ebp) /* Control if the column counter is = 3 (the last)*/ jne calculateSum /* If is different i go to calculateSum*/ DoSubtraction: movl -28(%ebp), %ebx /* If I stay here is becouse I have finished the column*/ movl -28(%ebp), %eax /* of the current row so now I move the row counter in %ebx*/ fldl -88(%ebp,%eax,8) /* and %eax! After i multiply this counter for 8byte and */ fsubl -16(%ebp) /* push in FPU register the known value calcoulated and */ movl -28(%ebp), %edx /* subtract from it the value stored in -16(%ebp)! After */ movl -28(%ebp), %ecx /* I move the row counter in %edx and %ecx*/ movl %edx, %eax /* Find the cell of matrix that I must use in this */ addl %eax, %eax /* time using the same code used first */ addl %edx, %eax addl %ecx, %eax movl -64(%ebp,%eax,4), %eax DoDivision: pushl %eax /* When I have found the cell that I want i push it*/ fildl (%esp) /* And read it as a double of 64bit*/ leal 4(%esp), %esp fdivrp %st, %st(1) /* I divide %st(1) the value of the prex subtraction and the value of matrix cell finded in the prev block of istruction! after pop %st and remain the result of the division in %st0 */ RefreshKnownValue: fstpl -88(%ebp,%ebx,8) /* Now I pop this value in the column of known value using the counter in %ebp multiplicated for 8Byte to obtain the correct index in witch store the value! */ leal -28(%ebp), %eax /* After incremente the value of row counter of 1*/ subl $1, (%eax) CalculateControlRow: cmpl $0, -28(%ebp) /* I Control if the row counter is = 0 */ jns ResetSumAndColCount /* If it is different i Jump to ResetSumAndColCount */ movl $msg4, (%esp) /* I stay here when I have finished all rows */ call printf /* print the msg4 */ movl $1, -20(%ebp) /* And create a new counter in -20(%ebp) */ jmp FinalControl /* Jump to the final control*/ PrintResult: movl -20(%ebp), %eax /* I move the value of counter in %eax*/ subl $1, %eax /* And decrement it becouse I must calculate the knowned value and I must start from 0 and this counter start from 1 becouse it is necessary to other things too*/ fldl -88(%ebp,%eax,8) /* After I push the exactly knowned value that I must use in FPU*/ fstpl 8(%esp) /* And pop it in 8(%esp)*/ movl -20(%ebp), %eax /* After move the counter in %eax */ movl %eax, 4(%esp) /* And move it in (%esp) becouse I must print it as index*/ movl $printdf, (%esp) /* So print the string printdf*/ call printf leal -20(%ebp), %eax /* After that increment the counter value*/ addl $1, (%eax) FinalControl: cmpl $4, -20(%ebp) /* I compare the counter with the value 4*/ jne PrintResult /* if it is different from 4 i jump to PrintResult*/ movl $0, (%esp) /* Exit procedure*/ call exit --------[bks.s]-------------------------------------------------------------------------------------------- [ 0x7 - Gauss's elimination of unknown variables to obtain a triangulate upper matrix ] Ok at this time we can said that if a system where rank(A) !=rank(A)|b| have not a solution!! A is a matrix of system and |b| is a vector of knowned values. for exemple the system 2x + 3y - 1z = 0 1x + 1y + 1z = 0 where A and b are : ---- ---- ---- --- | +2 | +3 | -1 | | 0 | A = ---- ---- ---- b = --- | +1 | +1 | +1 | | 0 | ---- ---- ---- --- the rank is the number of linear indipendents row! A row is linear indipendent when the sum of his value is different from zero so A1 = 2+3+1 = 6 != 0 A2 = 1+1+1 = 3 != 0 rank(A) = 2 since we have 2 linear indipendents row if we consider the A matrix with b vector in this case the rank not change : A1 = 2+3+1+0 =6 A2 = 1+1+1+0 =3 so since rank(A) = 2 = rank(A)|b we can obtain unfinished solution of this system! this solution dipends from the value that we want take to x y and z variables. In particoular we have oo^n-c solutions where : oo is unifinished n is the number of variables (x y z) c is the rank so we have oo^3-2 solution so oo^1! in a calculator oo^1 is different from oo^2 if the rank(A) is different from rank(A)|b the system don't have solutions: 2x + 3y - 1z = 1 4x + 6y - 2z = 5 is we multiply the first line for -2 we obtain this: (-2*2)x + (-2*3)y - (-2*1)z = -2*1 4x +6y -2z = 5 -4x -6y +2z = -2 +4x +6y -2z = 5 now if i sum the first with the second line I obtain this: (-4 +4)x + (-6+6)y + (2-2)z = -2+5 0x+0y+0z = 3 0 = 3 is not a valid result To resolve this type of system we must trasform a normal system in triangulate upper matrix and resolve it as did first.. so we consider only the 2x2 3x3 4x4 5x5 6x6 etc matrix! We use to solve it the Gauss's method For exemple the 3x3 matrix : 2x1 + 4x2 - 2x3 = 6 1x1 - 1x2 + 5x3 = 0 4x1 + 1x2 - 2x3 = 2 x2 x2 x3 x1 x2 x3 b ------------------- ------------------ --- a11 a12 a13 +2 +4 -2 6 ------------------- ------------------ --- a21 a22 a23 +1 -1 +5 0 ------------------- ------------------ --- a31 a32 a33 +4 +1 -2 2 ------------------- ------------------ --- to obtain the triangulate upper matrix i must "trasform" a21 = a31 = a32 = 0 SO: [TRANSFORM a21 = 0] [pass1] => a21 = a21/a11 = 1/2 [pass2] => multiply a21* (a11 a12 a13 b) = (1/2*2 ) (1/2*4) (1/2*-2) (1/2*6) = (1) (2) (-1) (3) [pass3] => subtract the obtenuted values to the (a21)(a22)(a23)(b) 1 -1 +5 0 - 1 +2 -1 3 = ----------------------------------- 0 -3 +6 +3 x1 x2 x3 b [pass4] => the new value of the row a21 a22 a23 b is : 0x1 -3x2 +6x3 = -3 2x1 + 4x2 - 2x3 = 6 0 - 3x2 + 6x3 = -3 4x1 + 1x2 - 2x3 = 2 [TRANSFORM a31 = 0] [pass1] => a31 = a31\a11 = 2 [pass2] => a31 * (a11 a12 a13 b) = (2*2) (2*4) (2*-2) (2*6) [pass3] => subract the obtenuted values to (a31) (a32) (a33) (b) 4 1 -2 2 - 4 8 -4 12 = ----------------------------- 0 -7 2 -10 x1 x2 x3 b [pass4] 2x1 + 4x2 - 2x3 = 6 0 - 3x2 + 6x3 = -3 0 - 7x2 + 2x3 = -10 [TRANSFORM a32 = 0] [pass1] => a32 = a32/a22 = 7/3 [pass2] => a32 * (a22 a23 b) = (7/3*0) (7/3*-3) (7/3*6) (7/3*-3) [pass3] => subtract the obtenuted values to (a32) (a33) (b) 0 -7 +2 -10 - 0 -7 14 -7 = ------------------------------- 0 0 -12 -3 [pass4] 2x1 + 4x2 - 2x3 = 6 0 - 3x2 + 6x3 = -3 0 + 0 - 12x3 = -3 Now we have obtenuted the triangulate upper matrix A X1 X2 X3 | B ---------------------|---- +2 +4 -2 | +6 ---------------------|---- 0 -3 +6 | -3 ---------------------|---- 0 0 -12 | -3 -------------------------- In general if we do this to resolve the linear system of nxn matrin in triangulate upper matrix [ a11 ] [ a12 ] [ a13 ]... [ a1n ] [ b1 ] [a21-(a21\a11)*a11] [a22-(a21\a11)*a12)] [a23-(a21\a11)*a13]... [a2n-(a21\a11)*a1n] [b2-(a21\a11)*b1] . . . [an1-(an1\a11)*a11] [an2-(an1\a11)*a12)] [an3-(an1\a11)*a13]... [ann-(an1\a11)*a1n] [bn-(an1\a11)*b1] to the end of this we obtain: [a11]| [a12 ] | [a1n ] | [b1 ] -----|-------------------|----------------|--------------- [ 0 ]| [a22(changed)] | [a2n(changed)] | [b2(changed)] -----|-------------------|----------------|--------------- . . . -----|-------------------|----------------|--------------- [ 0 ]| [an2(changed)] | [ann(changed)] | [bn(changed)] We must repeat the same operation until we have obtenuted the triangulate upper matrix! when we rewrite the new value of matrix instead to store the 0 value in the null cell we can store the multiplicand value calculate during the execution of gauss process! So the matrix first calculated is stored in calculator in this way ---------------------------- |[ X1 ]|[ X2 ]|[ X3 ] [ B ]| |======|======|====== ======| |[ +2 ]|[ +4 ]|[ -2 ] [ +6 ]| |======|------|------ ------| |[+1/2] [ -3 ]|[ +6 ] [ -3 ]| |====== ====== ------ ------| |[ +2 ]|[+7/3] [-12 ] [ -3 ]| ----------------------------