99#include "map.h"
1010
1111// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
12- static int doubling_primes [] = {7 , 19 , 43 , 89 , 179 , 347 , 647 , 1229 , 2297 , 4243 , 7829 , 14347 , 26017 , 47149 , 84947 , 152443 , 273253 , 488399 , 869927 , 1547173 , 2745121 , 4861607 };
12+ // prefixed with zero for the empty case.
13+ static int doubling_primes [] = {0 , 7 , 19 , 43 , 89 , 179 , 347 , 647 , 1229 , 2297 , 4243 , 7829 , 14347 , 26017 , 47149 , 84947 , 152443 , 273253 , 488399 , 869927 , 1547173 , 2745121 , 4861607 };
1314
1415int get_doubling_prime_greater_or_equal_to (int x ) {
1516 for (int i = 0 ; i < sizeof (doubling_primes ) / sizeof (int ); i ++ ) {
@@ -38,6 +39,31 @@ mp_map_t *mp_map_new(mp_map_kind_t kind, int n) {
3839 return map ;
3940}
4041
42+ void mp_map_clear (mp_map_t * map ) {
43+ map -> used = 0 ;
44+ machine_uint_t a = map -> alloc ;
45+ map -> alloc = 0 ;
46+ map -> table = m_renew (mp_map_elem_t , map -> table , a , map -> alloc );
47+ mp_map_elem_t nul = {NULL , NULL };
48+ for (uint i = 0 ; i < map -> alloc ; i ++ ) {
49+ map -> table [i ] = nul ;
50+ }
51+ }
52+
53+ static void mp_map_rehash (mp_map_t * map ) {
54+ int old_alloc = map -> alloc ;
55+ mp_map_elem_t * old_table = map -> table ;
56+ map -> alloc = get_doubling_prime_greater_or_equal_to (map -> alloc + 1 );
57+ map -> used = 0 ;
58+ map -> table = m_new0 (mp_map_elem_t , map -> alloc );
59+ for (int i = 0 ; i < old_alloc ; i ++ ) {
60+ if (old_table [i ].key != NULL ) {
61+ mp_map_lookup_helper (map , old_table [i ].key , true)-> value = old_table [i ].value ;
62+ }
63+ }
64+ m_del (mp_map_elem_t , old_table , old_alloc );
65+ }
66+
4167mp_map_elem_t * mp_map_lookup_helper (mp_map_t * map , mp_obj_t index , bool add_if_not_found ) {
4268 bool is_map_mp_obj = (map -> kind == MP_MAP_OBJ );
4369 machine_uint_t hash ;
@@ -46,6 +72,13 @@ mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_n
4672 } else {
4773 hash = (machine_uint_t )index ;
4874 }
75+ if (map -> alloc == 0 ) {
76+ if (add_if_not_found ) {
77+ mp_map_rehash (map );
78+ } else {
79+ return NULL ;
80+ }
81+ }
4982 uint pos = hash % map -> alloc ;
5083 for (;;) {
5184 mp_map_elem_t * elem = & map -> table [pos ];
@@ -54,17 +87,7 @@ mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_n
5487 if (add_if_not_found ) {
5588 if (map -> used + 1 >= map -> alloc ) {
5689 // not enough room in table, rehash it
57- int old_alloc = map -> alloc ;
58- mp_map_elem_t * old_table = map -> table ;
59- map -> alloc = get_doubling_prime_greater_or_equal_to (map -> alloc + 1 );
60- map -> used = 0 ;
61- map -> table = m_new0 (mp_map_elem_t , map -> alloc );
62- for (int i = 0 ; i < old_alloc ; i ++ ) {
63- if (old_table [i ].key != NULL ) {
64- mp_map_lookup_helper (map , old_table [i ].key , true)-> value = old_table [i ].value ;
65- }
66- }
67- m_del (mp_map_elem_t , old_table , old_alloc );
90+ mp_map_rehash (map );
6891 // restart the search for the new element
6992 pos = hash % map -> alloc ;
7093 } else {
@@ -106,6 +129,7 @@ void mp_set_init(mp_set_t *set, int n) {
106129
107130mp_obj_t mp_set_lookup (mp_set_t * set , mp_obj_t index , bool add_if_not_found ) {
108131 int hash = mp_obj_hash (index );
132+ assert (set -> alloc ); /* FIXME: if alloc is ever 0 when doing a lookup, this'll fail: */
109133 int pos = hash % set -> alloc ;
110134 for (;;) {
111135 mp_obj_t elem = set -> table [pos ];
0 commit comments