1 /*
2  *  Copyright (C) 1996-2017 Edward F. Valeev and Justin T. Fermann
3  *
4  *  This file is part of Libint.
5  *
6  *  Libint is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  Libint is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with Libint.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <libderiv/mem_man.h>
25 #define MAXALLOC 10000
26 
27 int free_block[MAXALLOC];   /* Marks of free-occupied blocks */
28 int block_length[MAXALLOC]; /* Keeps sizes of all blocks */
29 int last_free;              /* Number of the last free block */
30 int max_mem;                /* Amount of memory used by classes up to this point */
31 int mem_top;                /* Total memory allocated up to this point */
32 
33 /* initialize memory stack */
init_mem(int memory)34 void init_mem(int memory)
35 {
36   last_free = 1;
37   memset(free_block,0,MAXALLOC*sizeof(int));    /* All blocks are free */
38   memset(block_length,0,MAXALLOC*sizeof(int));  /* All of them are zero in length ... */
39   block_length[0] = memory;                     /* except for the first one */
40   max_mem = 0;
41   mem_top = memory;
42 }
43 
44 /* add memory */
add_mem(int memory)45 void add_mem(int memory)
46 {
47   int i;
48   int addto = 0;
49   int himem = 0;
50 
51   mem_top += memory;
52   /* Find the last free block and add all this memory to it */
53   for(i=0; i<last_free; i++){
54     if(free_block[i] > himem){
55       himem = free_block[i];
56       addto = i;
57       }
58     }
59 #if 0
60   printf("adding %d to memory\n\tnew top = %d\n", memory,
61     free_block[addto]+block_length[addto]+memory);
62 #endif
63   block_length[addto] = block_length[addto]+memory;
64 }
65 
66 /* Find a block of the requested size */
get_mem(int size)67 int get_mem(int size)
68 {
69   int i, j;
70 
71 /* try to find one that fits exactly */
72   for(i=last_free-1; i>=0; i--){
73     if(block_length[i] == size){
74       j = free_block[i];
75       if(free_block[i]+block_length[i]==mem_top) add_mem(500);
76       use(i, size);
77       return j;
78       }
79     }
80 
81 /* ok, try to find a bigger one that will work */
82   for(i=last_free-1; i>=0; i--){
83     if(block_length[i] > size){
84       j = free_block[i];
85       use(i, size);
86       return j;
87       }
88     }
89 
90 
91 /* last resort, expand memory */
92   add_mem(1000);
93   return get_mem(size);
94 
95 }
96 
97 
use(int n,int s)98 void use(int n, int s)
99 {
100   int i;
101 #if 0
102   printf("issuing %d doubles starting at %d out of free block %d\n",
103         s, free_block[n], n);
104   printf("last_free = %d\n", last_free);
105 #endif
106   if(s==block_length[n]){
107     for(i=n; i<last_free; i++){
108       free_block[i] = free_block[i+1];
109       block_length[i] = block_length[i+1];
110       }
111     last_free--;
112     }
113   else if(s<block_length[n]){
114     free_block[n] = free_block[n]+s;
115     block_length[n] = block_length[n]-s;
116 /* keep track of how much memory we use overall */
117     if(free_block[n]>max_mem) max_mem = free_block[n];
118     }
119   else exit(1);
120 
121 }
122 
free_mem(int n,int size)123 void free_mem(int n, int size)
124 {
125   int i, j;
126 
127   free_block[last_free] = n;
128   block_length[last_free] = size;
129   last_free++;
130 
131   consolidate();
132 
133 }
134 
consolidate()135 void consolidate()
136 {
137   int i, j;
138   int right_bound_i;
139   int done = 1;
140 
141   do {
142     done = 1;
143     for(i=0; i<last_free; i++){
144       right_bound_i = free_block[i]+block_length[i];
145       for(j=0; j<last_free; j++){
146         if(free_block[j]==right_bound_i){
147           block_length[i]+=block_length[j];
148           use(j, block_length[j]);
149           done = 0;
150           }
151         }
152       }
153     } while (!done);
154 #if 0
155   printf("after consolidation, free_blocks looks like:\n");
156   for(i=1; i<=last_free; i++){
157     printf("%d[%d]\t", free_block[i-1], block_length[i-1]);
158     if(!(i%5)) printf("\n");
159     }
160   printf("\n");
161 #endif
162 
163 }
164 
get_total_memory()165 int get_total_memory()
166 {
167   return max_mem;
168 }
169 
170