1/* 2Copyright (C) 2001-2014, Parrot Foundation. 3 4=head1 NAME 5 6src/pmc/resizablefloatarray.pmc - ResizableFloatArray PMC 7 8=head1 DESCRIPTION 9 10This class, C<ResizableFloatArray>, implements an array of resizable size, 11which stores FLOATVALs. It uses Float PMCs to do all necessary conversions. 12 13=head2 Functions 14 15=over 4 16 17=cut 18 19*/ 20 21/* HEADERIZER HFILE: none */ 22/* HEADERIZER BEGIN: static */ 23/* HEADERIZER END: static */ 24 25pmclass ResizableFloatArray extends FixedFloatArray auto_attrs provides array { 26 ATTR INTVAL resize_threshold; /* max size before array needs resizing */ 27 28/* 29 30=item C<FLOATVAL get_number_keyed_int(INTVAL key)> 31 32Returns the floating-point value of the element at index C<key>. 33 34=cut 35 36*/ 37 38 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) :no_wb { 39 FLOATVAL *float_array; 40 INTVAL size; 41 GET_ATTR_size(INTERP, SELF, size); 42 43 if (key < 0) 44 key += size; 45 if (key < 0) 46 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 47 "index out of bounds"); 48 if (key >= size) 49 return 0.0; 50 51 GET_ATTR_float_array(INTERP, SELF, float_array); 52 return float_array[key]; 53 } 54 55/* 56 57=item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)> 58 59Sets the floating-point value of the element at index C<key> to 60C<value>. 61 62=cut 63 64*/ 65 66 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) { 67 FLOATVAL *float_array; 68 INTVAL size; 69 GET_ATTR_size(INTERP, SELF, size); 70 71 if (key < 0) 72 key += size; 73 if (key < 0) 74 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 75 "index out of bounds"); 76 77 if (key >= size) 78 SELF.set_integer_native(key + 1); 79 80 GET_ATTR_float_array(INTERP, SELF, float_array); 81 float_array[key] = value; 82 } 83 84/* 85 86=item C<void set_integer_native(INTVAL size)> 87 88Resizes the array to C<size> elements. 89 90When growing, if the new size stays smaller than twice the old size, 91grow to twice the old size; otherwise, grow to the new size. 92 93When shrinking, if the new size is smaller than half the old size, 94shrink to one and half times the new size (which is less than or 95equal to three quarters of the old size). 96 97=cut 98 99*/ 100 101 VTABLE void set_integer_native(INTVAL size) { 102 FLOATVAL *float_array; 103 INTVAL resize_threshold; 104 105 if (size < 0) 106 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 107 "illegal argument"); 108 109 GET_ATTR_float_array(INTERP, SELF, float_array); 110 GET_ATTR_resize_threshold(INTERP, SELF, resize_threshold); 111 if (!float_array) { 112 /* empty - used fixed routine */ 113 if (size < 8) { 114 SUPER(8); 115 SET_ATTR_size(INTERP, SELF, size); 116 SET_ATTR_resize_threshold(INTERP, SELF, 8); 117 } 118 else { 119 SUPER(size); 120 SET_ATTR_resize_threshold(INTERP, SELF, size); 121 } 122 } 123 else if (size <= resize_threshold){ 124 /* we could shrink here if necessary */ 125 SET_ATTR_size(INTERP, SELF, size); 126 return; 127 } 128 else { 129 INTVAL cur = resize_threshold; 130 if (cur < 8192) 131 cur = size < 2 * cur ? 2 * cur : size; 132 else { 133 const INTVAL needed = size - cur; 134 cur += needed + 4096; 135 cur &= ~0xfff; 136 } 137 SET_ATTR_float_array(INTERP, SELF, 138 mem_gc_realloc_n_typed(INTERP, float_array, cur, FLOATVAL)); 139 SET_ATTR_size(INTERP, SELF, size); 140 SET_ATTR_resize_threshold(INTERP, SELF, cur); 141 } 142 } 143 144/* 145 146=item C<PMC *clone()> 147 148Creates and returns a copy of the array. 149 150=cut 151 152*/ 153 154 VTABLE PMC *clone() :no_wb { 155 INTVAL size; 156 PMC * const copy = SUPER(); 157 158 /* copy trimmed extra space */ 159 GET_ATTR_size(INTERP, SELF, size); 160 SET_ATTR_resize_threshold(INTERP, copy, size); 161 162 return copy; 163 } 164 165/* 166 167=item C<void push_float(FLOATVAL value)> 168 169Adds C<value> to the end of the array. 170 171=cut 172 173*/ 174 175 VTABLE void push_float(FLOATVAL value) :manual_wb { 176 const INTVAL nextix = SELF.elements(); 177 SELF.set_number_keyed_int(nextix, value); 178 } 179 180/* 181 182=item C<FLOATVAL pop_float()> 183 184Removes and returns the last element in the array. 185 186=cut 187 188*/ 189 190 VTABLE FLOATVAL pop_float() :manual_wb { 191 FLOATVAL value; 192 INTVAL size; 193 GET_ATTR_size(INTERP, SELF, size); 194 195 if (size == 0) 196 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 197 "Can't pop from an empty array"); 198 199 value = SELF.get_number_keyed_int(size-1); 200 SELF.set_integer_native(size - 1); 201 return value; 202 } 203/* 204 205=item C<INTVAL shift_float()> 206 207Removes and returns an item from the start of the array. 208 209=cut 210 211*/ 212 213 VTABLE FLOATVAL shift_float() { 214 FLOATVAL value, *float_array; 215 INTVAL size; 216 217 GET_ATTR_size(INTERP, SELF, size); 218 219 if (size == 0) 220 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 221 "Can't shift from an empty array"); 222 223 GET_ATTR_float_array(INTERP, SELF, float_array); 224 value = float_array[0]; 225 SET_ATTR_size(INTERP, SELF, --size); 226 227 memmove(float_array, float_array + 1, size * sizeof (FLOATVAL)); 228 return value; 229 } 230 231/* 232 233=item C<void unshift_float(FLOATVAL value)> 234 235Add and integer to the start of the array. 236 237=cut 238 239*/ 240 241 VTABLE void unshift_float(FLOATVAL value) { 242 INTVAL size; 243 FLOATVAL *float_array; 244 245 GET_ATTR_size(INTERP, SELF, size); 246 SELF.set_integer_native(size + 1); 247 GET_ATTR_float_array(INTERP, SELF, float_array); 248 memmove(float_array + 1, float_array, size * sizeof (FLOATVAL)); 249 float_array[0] = value; 250 } 251 252} 253 254/* 255 256=back 257 258=head1 SEE ALSO 259 260F<docs/pdds/pdd17_basic_types.pod>. 261 262=cut 263 264*/ 265 266/* 267 * Local variables: 268 * c-file-style: "parrot" 269 * End: 270 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : 271 */ 272