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