File: program.txt

package info (click to toggle)
jed 0.98.7-14
  • links: PTS
  • area: main
  • in suites: slink
  • size: 3,088 kB
  • ctags: 3,851
  • sloc: ansic: 29,315; makefile: 257; sh: 248
file content (195 lines) | stat: -rw-r--r-- 5,874 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
This document provides some tips for writing better and more efficient
S-Lang code.  It is not meant to be a tutorial on S-Lang.

Writing Fast Routines
=====================

  The first thing that one must realize is that S-Lang is an interpreted
  language and runs much slower than a compiled language.  This fact can be
  used to justify a rule of thumb that may be used to gauge the speed of a
  S-Lang expression:

    Rule of Thumb: All single token intrinsic statements and expressions run
		   at the same speed.

  The phrase ``intrinsic statements and expressions'' includes not only
  intrinsic functions but also assignment operations as well as pushing an
  object on the stack.  For example, consider the expression:
  
     n = down (20);
     
   This expression consists of the operation of pushing `20' onto the stack
   followed by calling the intrinsic function `down' and assigning it to
   `n'.  It is easiest to see this using the RPN form:
   
   .  20 down =n
   
   (Remember, all RPN expressions must lie on lines that begin with a
   period.).   From the above rule of thumb, this expression executes at a
   speed of 3 units.
   
   Now consider something more tricky.  Consider the expression:
   
       n = n + 1;
       
   It also executes in 3 units of time.  This is equivalent to:
   
       n++;
       
   However, `n++' is a single token and executes in 1 unit of time!  So, the
   rule is that one should try to use the `++' and `--' forms whenever
   possible.  The same statement is true for the `+=' and `-=' operators.
   The statement:
   
      n += 1;
      
   parses to two tokens:
   
   .  1 +=n;
   
   and executes in 2 units.  Note that 
   
      n++; n++;
      
   also achieves the effect `n = n + 2' but executes in 2 units as well.
   
       * Note:  These special forms are currently limited for integers and
                do not work with variables that represent floating point 
		values.
   
   At this point, it should be clear that the code that executes the fastest
   is the code that contains the least number of tokens.   However, this is
   only partially true and only holds for expressions that do not call other
   S-Lang functions.
   
   As an example, consider the recursive function below:
   
       define fib ();   % definition required for recursion
       
       define fib(n)
       {
          if (n == 0) return(0);
          if (n == 1) return(1);
  
          return fib(n - 1) + fib(n - 2);
       }
       
   The first thing to do is to change
   
         if (n == 0) return 0;
	 
   to 
         !if (n) return 0;
	 
   since the expression `n == 0' executes in 3 units and `n' executes in
   only 1.  Similarly, the statement:
   
         if (n == 1) return 1;
	 
   may be written:
   
         n--; !if (n) return 1;
  
   with the side effect that n is reduced by 1 in the process.  But that is
   a good thing because we can then modify:
   
       return fib (n - 1) + fib (n - 2);
       
   to:
   
       return fib(n) + fib (n - 1);
       
   Actually, we can do better than that.  We can write `n - 1' which
   executes in 3 units to the equivalent expression `n--, n' that executes
   in 2 units to produce:
   
      return fib (n) + fib (n--, n);
      
   Here the fact that `n--' does not affect the stack makes this possible.
   Finally, we are left with:
   
      define fib (n)
      {
        !if (n) return 0;
	n--; !if (n) return 1;
	return fib(n) + fib (n--, n);
      }

   Simply counting tokens (if, !if, fib, n, ==, 1, -, etc...) shows that the
   unoptimized version has 19 whereas the optimized version has 12. Applying
   the rule of thumb to this suggests that the optimized version should run
   19/12 times faster!  The reader is encouraged to compare the speed of the
   first version of `fib' with the optimized version to verify that this is
   indeed the case (use something like fib(25)).
   
   Here is a brief summary of what to do to squeeze extra speed out of
   S-Lang: 
   
      1.  Use the `++', `--', `+=', and `-=' forms wherever possible.
      2.  Eliminate `if (something == 0)' in favor of `!if (something)'
      3.  Avoid `while(1)' and use `forever' instead.
      4.  For simple looping a fixed number of times use `loop'.
      5.  If you have something like:
      
            for (i = imin; i <= imax; i += di) 
	      {
	         ...
	      }
	    
	  replace it by the MUCH faster and smaller version
	  
	    _for (imin, imax, di)
	       {
	         i = ();
		   .
		   .
	       }
	       
      6.  For multiplication by 2 use the `mul2' function.  
      7.  To square a number, do not use `x * x'.  Use `sqr(x)'.
      

Writing Memory Efficient Routines
=================================

   In the previous section, it was emphasized that routines that use the
   least number of tokens are the fastest.  Since they use the smallest
   number of tokens, they take up less space and and are more memory
   efficient.  
   
   Avoid the use of literal strings wherever possible.  Strings take up more
   memory than variables assigned to strings.  For example,
   
     define silly ()
     {
        if (file_exists ("my_file.txt")) 
	  rename ("my_file.txt", "my_file.old");
	else create ("my_file.txt");
     }
     
   should be written:
   
     define silly ()
     {
        variable file = "my_file.txt";
        if (file_exists (file)) 
          rename (file, "my_file.old");
        else create (file);
     }

   Similarly, when working with strings with 1 character, e.g., "a", if
   possible, use routines that work with characters instead.  For example,
   instead of using:
   
      insert ("a");      
      if (looking_at ("a")) ...
      
   use:
   
      insert_char ('a');
      if (looking_at_char ('a')) ...
      
   Finally, never use `""'; use `Null_String' instead.