HOME | 14. GUI | Try Sather | download | Post Messages |
Function factorial(n) in ffact.f returns factorial of n. The function is called from the sather part of the program (ffact.sa)
[code 1a]: ffact.f
01: integer function factorial(n) 02: integer n 03: factorial = 1 04: do i=1,n 05: factorial = factorial * i 06: enddo 07: return 08: end[code 1b]: ffact.sa
01: -- interface with fortran 02: -- to compile: 03: -- sacomp ffact.sa -external FACT ffact.f -o ffact 04: 05: 06: external FORTRAN class FACT is -- declare an external class written in Fortran 07: factorial(i:F_INTEGER):F_INTEGER; -- function defined in FACT 08: end; 09: 10: class MAIN is 11: main(av:ARRAY{STR}) is 12: i:F_INTEGER := #(av[1].cursor.get_int); -- integer of Fortran is F_INTEGER in Sather 13: a:F_INTEGER := FACT::factorial(i); -- an instance of F_INTEGER is created by #(INT) 14: #OUT + av[1] + "! = " + a.str + "\n"; -- convert to string by str method 15: end; 16: end;
You have to tell the compiler that FACT is defined in ffact.f using the -external flag.
$ sacomp ffact.sa -external FACT ffact.f -o ffact $ ./ffact 10 10! = 3628800Several Fortran data types such as F_INTEGER and F_REAL are available. You can create a instance of these data types by the create method with giving a corresponding Sather data type as an argument. See Sather — A Language Tutorial: Chapter 13 Interfacing with Fortran for detailed information.
Codes mat.f ([code 2a]) and mat.sa ([code 2b]) show Fortran and Sather part of matrices product calculation. Be aware that the order of line index and column index is different in Fortran (column, line) and (line, column) in Sather.
[code 2a]: mat.f
01: c 02: c calculating the product of matrices c = a * b 03: c 04: subroutine mattimes(l,m,n,a,b,c) 05: integer l,m,n,i,j,k 06: real a(n,l), b(m,n), c(m,l), tmp 07: do i=1,l 08: do j=1,m 09: tmp=0.0 10: do k=1,n 11: tmp=tmp+a(k,i)*b(j,k) 12: enddo 13: c(j,i)=tmp 14: enddo 15: enddo 16: return 17: end[code 2b]: mat.sa
01: -- Matrix test 02: -- sacomp mat.sa -chk -external FMAT mat.f -o mat 03: 04: external FORTRAN class FMAT is 05: mattimes(l,m,n:F_INTEGER, a,b,c:F_ARRAY2{F_REAL}); 06: end; 07: 08: class MAT is 09: include ARRAY2{FLT}; -- MAT class inherits ARRAY2{FLT} 10: 11: times(b:SAME):SAME -- define product 12: pre self.nc = b.nr -- check if the column number of the left side and line number of right side is same. 13: is 14: c:SAME:=#(self.nr, b.nc); -- declare a result storing matrix 15: FMAT::mattimes(#(self.nr), #(b.nc), #(self.nc), #(self), #(b), #(c)); -- calling mattimes from the Fortran module. 16: return c; -- values in F_ARRAY2{REAL} and ARRAY2{FLT} change simultaneously 17: end; 18: end; 19: 20: class MAIN is 21: main is 22: i:INT; 23: a,b,c:MAT; 24: a:=#(||1.0, 1.0, 2.0|, |2.0, 2.0, 3.0||); 25: b:=#(||1.0, 1.0|, |1.0, 2.0|, |1.0, 3.0||); 26: c:=a*b; -- matrices product calculation gets simple 27: 28: loop -- showing the answer 29: i:=1.up!; 30: #OUT + c.elt!; 31: if i%c.nc=0 then #OUT+"\n"; 32: else #OUT+" "; 33: end; 34: end; 35: end; 36: end;The mat calculates
$ sacomp mat.sa -chk -external FMAT mat.f -o mat $ ./mat 4 9 7 15
[code 3a]: cfact.c
01: unsigned long factorial(unsigned long i){ 02: unsigned long j, n; 03: for(n=1,j=1;j<=i;++j) n*=j; 04: return n; 05: }[code 3b] cfact.sa
01: -- interfacing with C 02: -- to compile: 03: -- sacomp cfact.sa -external FACT cfact.c -o cfact 04: -- 05: 06: external C class FACT is 07: factorial(i:C_UNSIGNED_LONG):C_UNSIGNED_LONG; 08: end; 09: 10: class MAIN is 11: main(av:ARRAY{STR}) is 12: i:C_UNSIGNED_LONG := #(av[1].cursor.get_int); 13: a:C_UNSIGNED_LONG := FACT::factorial(i); 14: #OUT + av[1] + "! = " + a.str + "\n"; 15: end; 16: end;The C language data types are named 'C_' + (data type in C (capital)) like C_CHAR and C_FLOAT. Instances of these data types are created by the create method with an argument of corresponding Sather data type. See Sather — A Language Tutorial: Chapter 14 Interfacing with ANSI C for detail.
You can compile and execute the program in a similar way to that of Fortran (ffact).
$ sacomp cfact.sa -external FACT cfact.c -o cfact $ ./cfact 10 10! = 3628800
I will show a pointer version of the encryption program (crypt.sa). As you cannot operate the XOR of the Sather CHAR type, you should convert the string data into array of INT. This part get efficient by using the C language, in which XOR of char is defined.
Following codes (encrypt.c ([code 4a]) and encrypt.sa ([code 4b])) show the improved version.
[code 4a]: encrypt.c
01: void encrypt(char* key, char* plain, char* cipher){ 02: char *key1, *plain1, *cipher1; 03: for(key1=key, plain1=plain, cipher1=cipher; *plain1 != 0; key1++, plain1++, cipher1++){ // the function expects that the string end with null 04: if(*key1==0) key1=key; // reuse the key 05: *cipher1 = *key1 ^ *plain1; // XOR of each bit 06: } 07: *cipher1=0; // add null at the end 08: }[code 4b] crypt.sa (partial)
01: external C class ENCRYPT is -- declare external class ENCRYPT 02: encrypt(key,plain,cipher:C_CHAR_PTR); 03: end; 04: 05: class ARCHAR is -- ARRAY{CHAR} + methods to convert from/to STR 06: include ARRAY{CHAR}; 07: 08: create(s:STR):SAME is -- create from STR 09: res:SAME:=#(s.size); 10: loop 11: res.set!(s.elt!); 12: end; 13: return res; 14: end; 15: 16: to_str:STR is -- convert to STR 17: fs:FSTR:=#(self.size); 18: loop 19: fs:=fs+self.elt!; 20: end; 21: return fs.str; 22: end; 23: end; -- ARCHAR 24: 25: class XOR < $CRYPT is 26: 27: private attr akey:ARCHAR; 28: 29: create(key0:STR):SAME is 30: return new.init(key0); 31: end; 32: 33: private init(key0:STR):SAME is 34: akey:=#(key0); 35: return self; 36: end; 37: 38: encrypt(s:STR):STR is 39: pl:ARCHAR:=#(s); 40: ci:ARCHAR:=#(s.size); 41: ENCRYPT::encrypt(#(akey.array_ptr), #(pl.array_ptr), #(ci.array_ptr)); -- calling the C function 42: return ci.to_str; 43: end; 44: 45: decrypt(s:STR):STR is -- decrypt is same as the encrypt 46: return encrypt(s); 47: end; 48: end; -- end of XORFunctions written in the C language that expect strings end with the null character work properly. Maybe it adds the null character at the end when it converts ARRAY{CHAR} into C_CHAR_PTR
Compile and run the program then you will get following output.
$ sacomp crypt.sa -external ENCRYPT encrypt.c -o crypt
$ ./crypt 'hello world! beautiful beautiful!'
Cipher Test using "hello world! beautiful beautiful!"
Plain send: hello world! beautiful beautiful!
Plain receive: hello world! beautiful beautiful!
XOR send: (non graphical string)
XOR receive: hello world! beautiful beautiful!
Download and play with the code in this chapter.
HOME | 14. GUI | Try Sather | download | Post Messages |