kdanylov aka koder | cdfcdaf | 2017-04-29 10:03:39 +0300 | [diff] [blame^] | 1 | #include <algorithm> |
| 2 | #include <cstdint> |
| 3 | #include <cstdio> |
| 4 | |
| 5 | extern "C" |
| 6 | void interpolate_ts_on_seconds_border( |
| 7 | unsigned int input_size, |
| 8 | unsigned int output_size, |
| 9 | uint64_t * times, |
| 10 | uint64_t * values, |
| 11 | unsigned int time_scale_coef, |
| 12 | uint64_t * output) |
| 13 | { |
| 14 | auto first_output_cell = (*times / time_scale_coef) * time_scale_coef; |
| 15 | auto input_cell_end = *times - time_scale_coef; // hack to unify loop |
| 16 | uint64_t input_cell_begin; |
| 17 | |
| 18 | // std::printf("first_output_cell = %ld\n", (long)first_output_cell); |
| 19 | |
| 20 | for(auto curr_times=times, curr_data_ptr=values; |
| 21 | curr_times < times + input_size ; ++curr_times, ++curr_data_ptr) |
| 22 | { |
| 23 | // take next cell from input array and calculate data rate in it |
| 24 | auto data_left = *curr_data_ptr; |
| 25 | input_cell_begin = input_cell_end; |
| 26 | input_cell_end = *curr_times; |
| 27 | |
| 28 | auto rate = data_left / double(input_cell_end - input_cell_begin); |
| 29 | |
| 30 | // std::printf("input_cell_begin=%ld input_cell_end=%ld\n", (long)input_cell_begin, (long)input_cell_end); |
| 31 | // std::printf("rate = %lf data_left=%ld\n", rate, (long)data_left); |
| 32 | |
| 33 | uint32_t first_output_cell_idx; |
| 34 | if (input_cell_begin <= first_output_cell) |
| 35 | first_output_cell_idx = 0; |
| 36 | else |
| 37 | // +1 because first_output_cell is actually the end of first cell |
| 38 | first_output_cell_idx = (input_cell_begin - first_output_cell) / time_scale_coef + 1; |
| 39 | |
| 40 | uint32_t last_output_cell_idx = (input_cell_end - first_output_cell) / time_scale_coef; |
| 41 | |
| 42 | if ((input_cell_end - first_output_cell) % time_scale_coef != 0) |
| 43 | ++last_output_cell_idx; |
| 44 | |
| 45 | last_output_cell_idx = std::min(last_output_cell_idx, output_size - 1); |
| 46 | |
| 47 | // std::printf("fidx=%d lidx=%d\n", (int)first_output_cell_idx, (int)last_output_cell_idx); |
| 48 | |
| 49 | for(auto output_idx = first_output_cell_idx; output_idx <= last_output_cell_idx ; ++output_idx) |
| 50 | { |
| 51 | // current output cell time slot |
| 52 | auto out_cell_begin = output_idx * time_scale_coef + first_output_cell - time_scale_coef; |
| 53 | auto out_cell_end = out_cell_begin + time_scale_coef; |
| 54 | auto slot = std::min(out_cell_end, input_cell_end) - std::max(out_cell_begin, input_cell_begin); |
| 55 | |
| 56 | auto slice = uint64_t(rate * slot); |
| 57 | |
| 58 | // std::printf("slot=%ld slice=%lf output_idx=%ld\n", (long)slot, (double)slice, (long)output_idx); |
| 59 | |
| 60 | data_left -= slice; |
| 61 | output[output_idx] += slice; |
| 62 | } |
| 63 | output[last_output_cell_idx] += data_left; |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | |
| 68 | extern "C" |
| 69 | void interpolate_ts_on_seconds_border_v2( |
| 70 | unsigned int input_size, |
| 71 | unsigned int output_size, |
| 72 | uint64_t * times, |
| 73 | uint64_t * values, |
| 74 | unsigned int time_step, |
| 75 | uint64_t * output) |
| 76 | { |
| 77 | auto output_end = (*times / time_step) * time_step; |
| 78 | auto output_begin = output_end - time_step; |
| 79 | auto output_cell = output; |
| 80 | |
| 81 | auto input_cell = values; |
| 82 | auto input_time = times; |
| 83 | auto input_val = *input_cell; |
| 84 | auto input_begin = *input_time - time_step; |
| 85 | auto input_end = *input_time; |
| 86 | auto rate = ((double)*input_cell) / (input_end - input_begin); |
| 87 | |
| 88 | // output array mush fully cover input array |
| 89 | while(output_cell < output + output_size) { |
| 90 | // check if cells intersect |
| 91 | auto intersection = ((int64_t)std::min(output_end, input_end)) - std::max(output_begin, input_begin); |
| 92 | |
| 93 | // add intersection slice to output array |
| 94 | if(intersection > 0) { |
| 95 | auto slice = (uint64_t)(intersection * rate); |
| 96 | *output_cell += slice; |
| 97 | input_val -= slice; |
| 98 | } |
| 99 | |
| 100 | // switch to next input or output cell |
| 101 | if (output_end >= input_end){ |
| 102 | *output_cell += input_val; |
| 103 | |
| 104 | ++input_cell; |
| 105 | ++input_time; |
| 106 | |
| 107 | if(input_time == times + input_size) |
| 108 | return; |
| 109 | |
| 110 | input_val = *input_cell; |
| 111 | input_begin = input_end; |
| 112 | input_end = *input_time; |
| 113 | rate = ((double)*input_cell) / (input_end - input_begin); |
| 114 | } else { |
| 115 | ++output_cell; |
| 116 | output_begin = output_end; |
| 117 | output_end += time_step; |
| 118 | } |
| 119 | } |
| 120 | } |