Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
blob: 6b9af78c22dce59c345ba0861c6ed0b15c858641 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/awk -f
#
# Performs interpolation for columns in a CSV and outputs the result
#
#   Copyright (C) 2016 LoVullo Associates, Inc.
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Configurable values (use -vname=value from command line):
#   step  - use predeterminated step instead of calculating from first two rows
##

function storeline()
{
  for ( i = 1; i <= hlen; i++ ) {
    prev[i] = $i
  }
}

function clearline()
{
  for ( i = 1; i <= hlen; i++ ) {
    prev[i] = 0
  }
}

function getprev()
{
  for ( i = 1; i <= hlen; i++ ) {
    $i = prev[i]
  }
}


function interpolate()
{
  lastval = prev[1]

  curval = $1
  diff = curval - lastval

  # does this value fall in line with the requested step?
  if ( diff == step )
  {
    storeline()

    # we're good; continue
    print
    next
  }

  # if we do not yet have a value large enough to reach our step, then continue
  # until we do (do not store this line)
  n = int( diff / step )
  if ( n <= 0 ) {
    next
  }

  # determine interpolation values
  for ( i = 2; i <= hlen; i++ ) {
    ival[i] = ( ( $i - prev[i] ) / n )
  }

  getprev()

  # let us interpolate values that are divisible by the step
  do
  {
    # increase the last value by our step
    $1 += step

    # interpolate each column value (notice that we skip the first column, which
    # was handled directly above)
    for ( i = 2; i <= hlen; i++ ) {
      $i += ival[i]
    }

    # print the new line
    print
  } while ( ( diff -= step ) > 0 )

  # anything remaining does not fit into our step and will be ignored; we'll
  # continue with our next step at the next line

  # consider this to be our last line
  storeline()
}


BEGIN {
  # the first row of the CSV is the header representing the column identifiers
  getline
  hlen = split( $0, header, /,/ )

  # output the header
  print $0

  # delimit fields by commas (the field separator for CSVs); note that this
  # won't work properly if strings contain commas
  FS = OFS = ","

  clearline()
  getline

  # if no step was provided, then calculate one based on the first two rows
  if ( step == 0 ) {
    # output the first row, which does not need to be interpolated
    print

    # compute the step
    vala = $1
    getline
    valb = $1
    step = valb - vala

    # since the second line is used to determine the step, then it must match the
    # step and therefore is good to output
    print

    # begin.
    storeline()
  }
}


# for each row
{ interpolate() }