The prelude contains the currently used definition of some Envision process.
//////////////////////////////////////////////////////////////////
/// abs
//////////////////////////////////////////////////////////////////
def autodiff const pure abs(n : number) as "abs" with
return if n < 0 then -n else n
def const pure abs(n : long) as "abs(long)" with
return if n < to.long(0) then -n else n
def const pure abs(n : double) as "abs(dbl)" with
return if n < to.double(0) then -n else n
//////////////////////////////////////////////////////////////////
/// isnan
//////////////////////////////////////////////////////////////////
def const pure isnan(n : number) as "isnan(num)" with
return n != n
def const pure isnan(n : double) as "isnan(dbl)" with
return n != n
//////////////////////////////////////////////////////////////////
/// gradControl (temporary)
//////////////////////////////////////////////////////////////////
def autodiff pure gradControl(x : number, y : number) as "gradControl" with
return noGrad(x)
//////////////////////////////////////////////////////////////////
/// format
//////////////////////////////////////////////////////////////////
def const pure format(m : month, format : text) as "format(mnth)" with
return format(monthStart(m), format)
def const pure format(m : week, format : text) as "format(week)" with
return format(monday(m), format)
//////////////////////////////////////////////////////////////////
/// loggamma
//////////////////////////////////////////////////////////////////
def autodiff pure logGamma(n : number) as "logGamma" with
// Log Gamma Function continued fractions NIST Handbook of Mathematical Functions see:
// https://univ.jeanpaulcalvi.com/Posters/ConfAuchWeb/abramovitz2.pdf
x = n + 1
// A & S eq. 6.1.48 (continuing fraction)
a0 = 1.0 / 12
a1 = 1.0 / 30
a2 = 53.0 / 210
a3 = 195.0 / 371
a4 = 22999.0 / 22737
// a5 = 29944523.0 / 19733142 // -> 1.5174736491532874
// a5 = 29944524.0 / 19733142 // approximated -> 1.5174736976623535
a5 = 1.5174736976623535
// a6 = 109535241009.0 / 48264275462 -> 2.26948902978545
// a6 = 109535240192.0 / 48264273920 // approximated -> 2.269489049911499
a6 = 2.269489049911499
t6 = a6 / x
t5 = a5 / (x + t6)
t4 = a4 / (x + t5)
t3 = a3 / (x + t4)
t2 = a2 / (x + t3)
t1 = a1 / (x + t2)
t0 = a0 / (x + t1)
// Ln2Pi_2 = Math.Log(2.0*Math.PI)/2.0
// Ln2Pi_2 = 0.9189385332
Ln2Pi_2 = 0.9189385
// Numeric shift to improve accuracy (cost +1 'Log').
// logGamma(x) = logGamma(x + 1) - log(x)
return -log(n) + t0 - x + (x - 0.5) * log(x) + Ln2Pi_2
//////////////////////////////////////////////////////////////////
/// loglikelihood.normal
//////////////////////////////////////////////////////////////////
def autodiff const pure loglikelihood_normal(mu : number, sigma : number, x : number) as "loglikelihood-normal" with
// return -0.9189385332 /* -Ln2Pi_2 */ - log(sigma) - (x - mu)^2 / (2 * sigma^2)
return -0.9189385 /* -Ln2Pi_2 */ - log(sigma) - (x - mu)^2 / (2 * sigma^2)
//////////////////////////////////////////////////////////////////
/// loglikelihood.poisson
//////////////////////////////////////////////////////////////////
def autodiff pure loglikelihood_poisson(lambda : number, k : number) as "loglikelihood-poisson" with
return k * log(lambda) - lambda - logGamma(k + 1)
//////////////////////////////////////////////////////////////////
/// loglikelihood.negativeBinomial
//////////////////////////////////////////////////////////////////
def autodiff pure loglikelihood_negativebinomial(mean : number, dispersion : number, k : number) as "loglikelihood-negativebinomial" with
y = 0
if dispersion >= 1.001
r = mean / (dispersion - 1)
p = 1 - 1 / dispersion
y = logGamma(k + r) - logGamma(k + 1) - logGamma(r) + k * log(p) + r * log(1 - p)
else
y = loglikelihood.poisson(mean, k)
return y
//////////////////////////////////////////////////////////////////
/// loglikelihood.zeroInflatedNegativeBinomial
//////////////////////////////////////////////////////////////////
def autodiff pure loglikelihood_negativebinomial(mean : number, dispersion : number, zeroInflation : number, k : number) as "loglikelihood-inflatednegativebinomial" with
y = 0
alpha = 0
if zeroInflation < 0
alpha = 0
else
if zeroInflation > 0.999
alpha = 0.999
else
alpha = zeroInflation
if dispersion >= 1.001
r = mean / (dispersion - 1)
p = 1 - 1 / dispersion
if k == 0
y = log(alpha + (1-alpha) * (1-p)^r)
else
y = logGamma(k + r) - logGamma(k + 1) - logGamma(r) + k * log(p) + r * log(1 - p) + log(1-alpha)
else
if k == 0
y = log(alpha + (1-alpha) * exp(-mean))
else
y = loglikelihood.poisson(mean, k)+log(1-alpha)
return y
//////////////////////////////////////////////////////////////////
/// loglikelihood.loglogistic
//////////////////////////////////////////////////////////////////
def autodiff pure loglikelihood_loglogistic(alpha : number, beta : number, x : number) as "loglikelihood-loglogistic" with
logAlpha = log(alpha)
return log(beta) - logAlpha + (beta - 1)*(log(x)-logAlpha)-2*log(1+(x/alpha)^beta)
//////////////////////////////////////////////////////////////////
/// loglikelihood.loglogistic (with lowerbound option)
//////////////////////////////////////////////////////////////////
def autodiff pure loglikelihood_loglogistic(alpha : number, beta : number, x : number, isLowerBound : boolean) as "loglikelihood-loglogistic-lowerbound" with
y = 0
if not isLowerBound
y = loglikelihood.logLogistic(alpha, beta, x)
else
y = log(1-1/(1+(alpha/x)^beta))
return y
//////////////////////////////////////////////////////////////////
/// square
//////////////////////////////////////////////////////////////////
def const pure square(n : number) as "square(num)" with
return n * n
//////////////////////////////////////////////////////////////////
/// weekDayNum
//////////////////////////////////////////////////////////////////
def const pure weekDayNum(d : date) as "weekDayNum" with
return d - monday(d) + 1
//////////////////////////////////////////////////////////////
/// Regularization Term
//////////////////////////////////////////////////////////////
def autodiff pure regularizationTerm(
/// the positive quantity that aims to impact parameters gradients
penalty: number,
/// The original loss, without any regularization terms
loss : number,
/// The scaling factor, intended to be between 0 (no impact) and 1 (regularization as important as original loss)
alpha : number) as "regularizationTerm" with
/// The penalty is scaled between 0 and 1 with a gradient that does not converge to 0
/// If the penalty is under 1.8 (magic number, after this value, tanh gradient is too small), one uses tanh
/// After this limit one uses the rest of the floor function.
/// Note that noGrad is used as the floor's gradient is hand coded as 1.
/// To make computation faster:
/// 1 - tanh(1.8)^2 = 0.10355837
/// tanh(1.8) = 0.94680601
scaledPenalty = if penalty < 1.8 then tanh(penalty) else 0.10355837*(penalty - floor(noGrad(penalty)/1.8) * 1.8) + 0.94680601
/// The scaled penalty (between 0 and 1) is then scaled by the original loss, used without impacting gradient.
return alpha * noGrad(loss) * scaledPenalty
//////////////////////////////////////////////////////////////////
/// single
//////////////////////////////////////////////////////////////////
def process single(a: number) as "single{num}" default 0 with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: text) as "single{text}" default "" with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: date) as "single{date}" default date(2001,1,1) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: boolean) as "single{bool}" default false with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: ranvar) as "single{dist}" default (dirac(0)) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: zedfunc) as "single{fun}" default (linear(0)) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: double) as "single{dbl}" default (to.double(0)) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: long) as "single{long}" default (to.long(0)) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: week) as "single{week}" default (week(date(2001, 1, 1))) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: month) as "single{mnth}" default (month(date(2001, 1, 1))) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: flagset) as "single{flag}" default (emptySet()) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: ordinal) as "single{ord}" default (bad_ord__()) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
def process single(a: embedding) as "single{emb}" default (bad_emb__()) with
if not argfirst()
b = assertfail("'single()': called with more than one element.")
return a
//////////////////////////////////////////////////////////////////
/// Sum/Product
//////////////////////////////////////////////////////////////////
def process sum(n : double) as "sum{dbl}" default (to.double(0)) with
keep accum = to.double(0)
accum = accum + n
return accum
def process sum(n : long) as "sum{long}" default (to.long(0)) with
keep accum = to.long(0)
accum = accum + n
return accum
def process sum(n : number) as "sum{num}" default 0 with
return to.number(sum(to.double(n)))
def process fastsum(n: number) as "fastsum{num}" default 0 with
keep accum = 0
accum = accum + n
return accum
def process product(n : number) as "product{num}" default 1 with
keep accum = to.double(1)
accum = accum * to.double(n)
return to.number(accum)
//////////////////////////////////////////////////////////////////
/// Average
//////////////////////////////////////////////////////////////////
def process avg(n : double) as "avg{dbl}" default to.double(0) with
return sum(n) / to.double(enumerate() + 1)
def process avg(n : long) as "avg{long}" default to.long(0) with
return sum(n) / to.long(enumerate() + 1)
def process avg(n : number) as "avg{num}" default 0 with
return to.number(avg(to.double(n)))
////////////////////////////////////////////////////////////////
/// any
////////////////////////////////////////////////////////////////
def process any(v : boolean) as "any{bool}" default false with
keep seen = false
seen = seen or v
return seen
////////////////////////////////////////////////////////////////
/// ratio
////////////////////////////////////////////////////////////////
def process ratio(val : number) as "ratio{num}" default 1 with
return count(val != 0) / (enumerate() + 1)
def process ratio(val : text) as "ratio{text}" default 1 with
return count(val != "") / (enumerate() + 1)
def process ratio(val : boolean) as "ratio{bool}" default 1 with
return count(val) / (enumerate() + 1)
////////////////////////////////////////////////////////////////
/// Set union and intersection
////////////////////////////////////////////////////////////////
def process union(n : flagset) as "union{flag}" default emptySet() with
keep acc = emptySet()
acc = union(acc, n)
return acc
def process intersection(n : flagset) as "intersection{flag}" default complement(emptySet()) with
keep acc = complement(emptySet())
acc = intersection(acc, n)
return acc
////////////////////////////////////////////////////////////////
/// all
////////////////////////////////////////////////////////////////
def process all(v : boolean) as "all{bool}" default true with
keep seen = true
seen = seen and v
return seen
//////////////////////////////////////////////////////////////////
/// enumerations
//////////////////////////////////////////////////////////////////
def process argfirst() as "is_first{}" default false with
keep isFirst = true
if isFirst
isFirst = false
return true
else
return false
def process argfirst(cond : boolean) as "is_first{bool}" default false with
keep answer = false
keep marked = true
if marked
if cond
marked = false
answer = true
else
answer = false
return answer
def process enumerate() as "enumerate{}" default 0 with
keep value = to.long(-1)
value = to.long(1) + value
return to.number(value)
def process rank() as "rank{}" default 0 with
keep value = to.long(0)
value = to.long(1) + value
return to.number(value)
def process rankrev() as "rev_enumerate{}" default 0 with
return groupsize() - enumerate()
//////////////////////////////////////////////////////////////////
/// Min (all versions)
//////////////////////////////////////////////////////////////////
def process min(a : number) as "min{num}" default 0 with
keep mini = 0
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : long) as "min{long}" default to.long(0) with
keep mini = to.long(0)
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : double) as "min{dbl}" default to.double(0) with
keep mini = to.double(0)
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : date) as "min{date}" default (date(2001, 1, 1)) with
keep mini = date(2001, 1, 1)
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : week) as "min{week}" default (week(date(2001, 1, 1))) with
keep mini = week(date(2001, 1, 1))
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : month) as "min{mnth}" default (month(date(2001, 1, 1))) with
keep mini = month(date(2001, 1, 1))
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : text) as "min{text}" default "" with
keep mini = ""
if argfirst()
mini = a
else if a < mini
mini = a
return mini
def process min(a : ranvar) as "min{ranv}" default (dirac(0)) with
keep mini = dirac(0)
if argfirst()
mini = a
else
mini = min(mini, a)
return mini
//////////////////////////////////////////////////////////////////
/// Max (all versions)
//////////////////////////////////////////////////////////////////
def process max(a : number) as "max{num}" default 0 with
keep maxi = 0
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : long) as "max{long}" default to.long(0) with
keep maxi = to.long(0)
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : double) as "max{dbl}" default to.double(0) with
keep maxi = to.double(0)
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : date) as "max{date}" default (date(2001, 1, 1)) with
keep maxi = date(2001, 1, 1)
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : week) as "max{week}" default (week(date(2001, 1, 1))) with
keep maxi = week(date(2001, 1, 1))
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : month) as "max{mnth}" default (month(date(2001, 1, 1))) with
keep maxi = month(date(2001, 1, 1))
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : text) as "max{text}" default "" with
keep maxi = ""
if argfirst()
maxi = a
else if a > maxi
maxi = a
return maxi
def process max(a : ranvar) as "max{ranv}" default (dirac(0)) with
keep maxi = dirac(0)
if argfirst()
maxi = a
else
maxi = max(maxi, a)
return maxi
//////////////////////////////////////////////////////////////////
/// count
//////////////////////////////////////////////////////////////////
def process count(n : boolean) as "count{bool}" default 0 with
keep c = to.long(0)
if n
c = c + to.long(1)
return to.number(c)
//////////////////////////////////////////////////////////////////
/// distinct
//////////////////////////////////////////////////////////////////
def process distinct(b : boolean) as "distinct{bool}" default 0 with
keep hasTrue = false
keep hasFalse = false
if b
hasTrue = true
else
hasFalse = true
return((if hasTrue then 1 else 0) + (if hasFalse then 1 else 0))
//////////////////////////////////////////////////////////////////
/// mode
//////////////////////////////////////////////////////////////////
def process mode(b : boolean) as "mode{bool}" default false with
keep trueCount = to.long(0)
keep falseCount = to.long(0)
if b
trueCount = trueCount + to.long(1)
else
falseCount = falseCount + to.long(1)
return trueCount > falseCount
//////////////////////////////////////////////////////////////////
/// areSame
//////////////////////////////////////////////////////////////////
def process areSame(a : number) as "areSame{num}" default true with
keep value = 0
if argfirst()
value = a
return all(a == value)
def process areSame(a : double) as "areSame{dbl}" default true with
keep value = to.double(0)
if argfirst()
value = a
return all(a == value)
def process areSame(a : long) as "areSame{long}" default true with
keep value = to.long(0)
if argfirst()
value = a
return all(a == value)
def process areSame(a : ordinal) as "areSame{ord}" default true with
keep value = bad_ord__()
if argfirst()
value = a
return all(a == value)
def process areSame(a : boolean) as "areSame{bool}" default true with
keep value = false
if argfirst()
value = a
return all(value == a)
def process areSame(a : date) as "areSame{date}" default true with
keep value = date(2001, 1, 1)
if argfirst()
value = a
return all(value == a)
def process areSame(a : week) as "areSame{week}" default true with
keep value = week(date(2001, 1, 1))
if argfirst()
value = a
return all(value == a)
def process areSame(a : month) as "areSame{mnth}" default true with
keep value = month(date(2001, 1, 1))
if argfirst()
value = a
return all(value == a)
// we don't use all, to avoid extra comparison that are not
// cheap for text, ranvar and zedfunc
def process areSame(a : text) as "areSame{text}" default true with
keep areSame = true
keep value = ""
if argfirst()
value = a
else if value != a
areSame = false
return areSame
def process areSame(a : ranvar) as "areSame{dist}" default true with
keep areSame = true
keep value = dirac(0)
if argfirst()
value = a
else if value != a
areSame = false
return areSame
def process areSame(a : zedfunc) as "areSame{fun}" default true with
keep areSame = true
keep value = linear(0)
if argfirst()
value = a
else if value != a
areSame = false
return areSame
def process areSame(a : embedding) as "areSame{emb}" default true with
keep areSame = true
keep value = bad_emb__()
if argfirst()
value = a
else if value != a
areSame = false
return areSame
//////////////////////////////////////////////////////////////////
/// same (it's the same)
//////////////////////////////////////////////////////////////////
def process same(a: number) as "same{num}" default 0 with
keep fst = 0
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: ordinal) as "same{ord}" default (bad_ord__()) with
keep fst = bad_ord__()
if argfirst()
fst = a
else if fst != a
fstStr = text(fst)
aStr = text(a)
b = assertfail("'same()': found different values '\{fstStr}' and '\{aStr}'.")
return a
def process same(a: date) as "same{date}" default date(2001,1,1) with
keep fst = date(2001,1,1)
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: boolean) as "same{bool}" default false with
keep fst = false
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: double) as "same{dbl}" default to.double(0) with
keep fst = to.double(0)
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: long) as "same{long}" default to.long(0) with
keep fst = to.long(0)
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: flagset) as "same{flag}" default emptySet() with
keep fst = emptySet()
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values.")
return a
def process same(a: week) as "same{week}" default week(date(2001,1,1)) with
keep fst = week(date(2001,1,1))
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: month) as "same{mnth}" default month(date(2001,1,1)) with
keep fst = month(date(2001,1,1))
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: ranvar) as "same{dist}" default dirac(0) with
keep fst = dirac(0)
if argfirst()
fst = a
else if fst != a
fstSpark = spark(fst)
aSpark = spark(a)
b = assertfail("'same()': found different values '\{fstSpark}' and '\{aSpark}'.")
return a
def process same(a: zedfunc) as "same{fun}" default linear(0) with
keep fst = linear(0)
if argfirst()
fst = a
else if fst != a
fstSpark = spark(fst)
aSpark = spark(a)
b = assertfail("'same()': found different values '\{fstSpark}' and '\{aSpark}'.")
return a
def process same(a: text) as "same{text}" default "" with
keep fst = ""
if argfirst()
fst = a
else if fst != a
b = assertfail("'same()': found different values '\{fst}' and '\{a}'.")
return a
def process same(a: embedding) as "same{emb}" default bad_emb__() with
keep fst = bad_emb__()
if argfirst()
fst = a
else if fst != a
fstSpark = spark(fst)
aSpark = spark(a)
b = assertfail("'same()': found different values '\{fstSpark}' and '\{aSpark}'.")
return a
//////////////////////////////////////////////////////////////////
/// argmin/max (all versions)
//////////////////////////////////////////////////////////////////
def process argmin(score: number, val: number) as "argmin{num,num}" default 0 with
keep minScore = 0
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: number, val: number) as "argmax{num,num}" default 0 with
keep maxScore = 0
keep maxi = 0
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
def process argmin(score: number, val: boolean) as "argmin{num,bool}" default false with
keep minScore = 0
keep mini = false
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: number, val: boolean) as "argmax{num,bool}" default false with
keep maxScore = 0
keep maxi = false
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
def process argmin(score: number, val: text) as "argmin{num,txt}" default "" with
keep minScore = 0
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: number, val: text) as "argmax{num,txt}" default "" with
keep maxScore = 0
keep maxi = ""
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
def process argmin(score: number, val: date) as "argmin{num,date}" default (date(2001,1,1)) with
keep minScore = 0
keep mini = date(2001,1,1)
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: number, val: date) as "argmax{num,date}" default (date(2001,1,1)) with
keep maxScore = 0
keep maxi = date(2001,1,1)
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
def process argmin(score: number, val: ordinal) as "argmin{num,ord}" default (bad_ord__()) with
keep minScore = 0
keep mini = bad_ord__()
if argfirst() or score < minScore
minScore = score
mini = val
return mini
def process argmax(score: number, val: ordinal) as "argmax{num,ord}" default (bad_ord__()) with
keep maxScore = 0
keep maxi = bad_ord__()
if argfirst() or score > maxScore
maxScore = score
maxi = val
return maxi
def process argmin(score: number, val: ranvar) as "argmin{num,dist}" default (dirac(0)) with
keep minScore = 0
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: number, val: ranvar) as "argmax{num,dist}" default (dirac(0)) with
keep maxScore = 0
keep maxi = dirac(0)
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
def process argmin(score: number, val: zedfunc) as "argmin{num,fun}" default (linear(0)) with
keep minScore = 0
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: number, val: zedfunc) as "argmax{num,fun}" default (linear(0)) with
keep maxScore = 0
keep maxi = linear(0)
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
def process argmin(score: date, val: boolean) as "argmin{date,bool}" default false with
keep minScore = date(2001, 1, 1)
keep mini = false
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: date, val: boolean) as "argmax{date,bool}" default false with
keep minScore = date(2001, 1, 1)
keep mini = false
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: date, val: number) as "argmin{date,num}" default 0 with
keep minScore = date(2001, 1, 1)
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: date, val: number) as "argmax{date,num}" default 0 with
keep minScore = date(2001, 1, 1)
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: date, val: ordinal) as "argmin{date,ord}" default (bad_ord__()) with
keep minScore = date(2001, 1, 1)
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: date, val: ordinal) as "argmax{date,ord}" default (bad_ord__()) with
keep minScore = date(2001, 1, 1)
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: date, val: ranvar) as "argmin{date,dist}" default (dirac(0)) with
keep minScore = date(2001, 1, 1)
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: date, val: ranvar) as "argmax{date,dist}" default (dirac(0)) with
keep minScore = date(2001, 1, 1)
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: date, val: text) as "argmin{date,txt}" default "" with
keep minScore = date(2001, 1, 1)
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: date, val: text) as "argmax{date,txt}" default "" with
keep minScore = date(2001, 1, 1)
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: date, val: zedfunc) as "argmin{date,fun}" default (linear(0)) with
keep minScore = date(2001, 1, 1)
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: date, val: zedfunc) as "argmax{date,fun}" default (linear(0)) with
keep minScore = date(2001, 1, 1)
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: week, val: boolean) as "argmin{week,bool}" default false with
keep minScore = week(date(2001, 1, 1))
keep mini = false
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: week, val: boolean) as "argmax{week,bool}" default false with
keep minScore = week(date(2001, 1, 1))
keep mini = false
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: week, val: number) as "argmin{week,num}" default 0 with
keep minScore = week(date(2001, 1, 1))
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: week, val: number) as "argmax{week,num}" default 0 with
keep minScore = week(date(2001, 1, 1))
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: week, val: ordinal) as "argmin{week,ord}" default (bad_ord__()) with
keep minScore = week(date(2001, 1, 1))
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: week, val: ordinal) as "argmax{week,ord}" default (bad_ord__()) with
keep minScore = week(date(2001, 1, 1))
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: week, val: ranvar) as "argmin{week,dist}" default (dirac(0)) with
keep minScore = week(date(2001, 1, 1))
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: week, val: ranvar) as "argmax{week,dist}" default (dirac(0)) with
keep minScore = week(date(2001, 1, 1))
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: week, val: text) as "argmin{week,txt}" default "" with
keep minScore = week(date(2001, 1, 1))
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: week, val: text) as "argmax{week,txt}" default "" with
keep minScore = week(date(2001, 1, 1))
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: week, val: zedfunc) as "argmin{week,fun}" default (linear(0)) with
keep minScore = week(date(2001, 1, 1))
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: week, val: zedfunc) as "argmax{week,fun}" default (linear(0)) with
keep minScore = week(date(2001, 1, 1))
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: month, val: boolean) as "argmin{mnth,bool}" default false with
keep minScore = month(date(2001, 1, 1))
keep mini = false
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: month, val: boolean) as "argmax{mnth,bool}" default false with
keep minScore = month(date(2001, 1, 1))
keep mini = false
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: month, val: number) as "argmin{mnth,num}" default 0 with
keep minScore = month(date(2001, 1, 1))
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: month, val: number) as "argmax{mnth,num}" default 0 with
keep minScore = month(date(2001, 1, 1))
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: month, val: ordinal) as "argmin{mnth,ord}" default (bad_ord__()) with
keep minScore = month(date(2001, 1, 1))
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: month, val: ordinal) as "argmax{mnth,ord}" default (bad_ord__()) with
keep minScore = month(date(2001, 1, 1))
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: month, val: ranvar) as "argmin{mnth,dist}" default (dirac(0)) with
keep minScore = month(date(2001, 1, 1))
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: month, val: ranvar) as "argmax{mnth,dist}" default (dirac(0)) with
keep minScore = month(date(2001, 1, 1))
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: month, val: text) as "argmin{mnth,txt}" default "" with
keep minScore = month(date(2001, 1, 1))
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: month, val: text) as "argmax{mnth,txt}" default "" with
keep minScore = month(date(2001, 1, 1))
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: month, val: zedfunc) as "argmin{mnth,fun}" default (linear(0)) with
keep minScore = month(date(2001, 1, 1))
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: month, val: zedfunc) as "argmax{mnth,fun}" default (linear(0)) with
keep minScore = month(date(2001, 1, 1))
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: boolean) as "argmin{txt,bool}" default false with
keep minScore = ""
keep mini = false
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: text, val: boolean) as "argmax{txt,bool}" default false with
keep minScore = ""
keep mini = false
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: number) as "argmin{txt,num}" default 0 with
keep minScore = ""
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: text, val: number) as "argmax{txt,num}" default 0 with
keep minScore = ""
keep mini = 0
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: ordinal) as "argmin{txt,ord}" default (bad_ord__()) with
keep minScore = ""
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: text, val: ordinal) as "argmax{txt,ord}" default (bad_ord__()) with
keep minScore = ""
keep mini = (bad_ord__())
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: ranvar) as "argmin{txt,dist}" default (dirac(0)) with
keep minScore = ""
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: text, val: ranvar) as "argmax{txt,dist}" default (dirac(0)) with
keep minScore = ""
keep mini = dirac(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: text) as "argmin{txt,txt}" default "" with
keep minScore = ""
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: text, val: text) as "argmax{txt,txt}" default "" with
keep minScore = ""
keep mini = ""
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: zedfunc) as "argmin{txt,fun}" default (linear(0)) with
keep minScore = ""
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score < minScore
minScore = score
mini = val
return mini
def process argmax(score: text, val: zedfunc) as "argmax{txt,fun}" default (linear(0)) with
keep minScore = ""
keep mini = linear(0)
if argfirst()
minScore = score
mini = val
else if score > minScore
minScore = score
mini = val
return mini
def process argmin(score: text, val: date) as "argmin{txt,date}" default (date(2001,1,1)) with
keep minScore = ""
keep mini = date(2001,1,1)
if argfirst()
minScore = score
mini = val
else if score < minScore
mini = val
minScore = score
return mini
def process argmax(score: text, val: date) as "argmax{txt,date}" default (date(2001,1,1)) with
keep maxScore = ""
keep maxi = date(2001,1,1)
if argfirst()
maxScore = score
maxi = val
else if score > maxScore
maxi = val
maxScore = score
return maxi
//////////////////////////////////////////////////////////////
/// Last of simple value only (complex would induce a copy
/// we don't want that)
//////////////////////////////////////////////////////////////
def process last(v : number) as "last{num}" default 0 with
return v
def process last(v : double) as "last{dbl}" default to.double(0) with
return v
def process last(v : long) as "last{long}" default to.long(0) with
return v
def process last(v : flagset) as "last{flag}" default emptySet() with
return v
def process last(v : date) as "last{date}" default date(2001,1,1) with
return v
def process last(v : month) as "last{mnth}" default month(date(2001,1,1)) with
return v
def process last(v : week) as "last{week}" default week(date(2001,1,1)) with
return v
def process last(v : boolean) as "last{bool}" default false with
return v
def process last(v : embedding) as "last{emb}" default bad_emb__() with
return v
// this could be, but not done due to the large performance impact
// keeping them in IL allows us to skip copy!
//
// def process last(v : text) as "last{text}" default "" with
// return v
//
// def process last(v : ranvar) as "last{dist}" default (dirac(0)) with
// return v
//
// def process last(v : zedfunc) as "last{fun}" default (linear(0)) with
// return v
//////////////////////////////////////////////////////////////
/// Whichever/first, whichever come first
//////////////////////////////////////////////////////////////
def process first(a: flagset) as "first{flag}" default emptySet() with
keep first = emptySet()
if argfirst()
first = a
return first
def process first(a: number) as "first{num}" default 0 with
keep first = 0
if argfirst()
first = a
return first
def process first(a: ordinal) as "first{ord}" default bad_ord__() with
keep first = bad_ord__()
if argfirst()
first = a
return first
def process first(a: text) as "first{text}" default "" with
keep first = ""
if argfirst()
first = a
return first
def process first(a: date) as "first{date}" default (date(2001, 1, 1)) with
keep first = date(2001, 1, 1)
if argfirst()
first = a
return first
def process first(a: month) as "first{mnth}" default (month(date(2001, 1, 1))) with
keep first = month(date(2001, 1, 1))
if argfirst()
first = a
return first
def process week(a: week) as "first{week}" default (week(date(2001, 1, 1))) with
keep first = week(date(2001, 1, 1))
if argfirst()
first = a
return first
def process first(a: boolean) as "first{bool}" default false with
keep first = false
if argfirst()
first = a
return first
def process first(a: ranvar) as "first{dist}" default (dirac(0)) with
keep first = dirac(0)
if argfirst()
first = a
return first
def process first(a: zedfunc) as "first{fun}" default (linear(0)) with
keep first = linear(0)
if argfirst()
first = a
return first
def process first(a: double) as "first{dbl}" default (to.double(0)) with
keep first = to.double(0)
if argfirst()
first = a
return first
def process first(a: long) as "first{long}" default (to.long(0)) with
keep first = to.long(0)
if argfirst()
first = a
return first
def process first(a: embedding) as "first{emb}" default bad_emb__() with
keep first = bad_emb__()
if argfirst()
first = a
return first
//////////////////////////////////////////////////////////////
/// smudge
//////////////////////////////////////////////////////////////
def process smudge(val : boolean, present: boolean) as "smudge{bool,bool}" default false with
keep tmp = false
if present
tmp = val
return tmp
def process smudge(val : number, present: boolean) as "smudge{num,bool}" default 0 with
keep tmp = 0
if present
tmp = val
return tmp
def process smudge(val : date, present: boolean) as "smudge{date,bool}" default date(2001,1,1) with
keep tmp = date(2001,1,1)
if present
tmp = val
return tmp
def process smudge(val : text, present: boolean) as "smudge{text,bool}" default "" with
keep tmp = ""
if present
tmp = val
return tmp
//////////////////////////////////////////////////////////////
/// expsmooth
//////////////////////////////////////////////////////////////
def process expsmooth(src: number, factor: number; init: number) as "expsmooth{num,num;num}" default 0 with
keep prev = init
prev = factor * src + (1 - factor) * prev
return prev
//////////////////////////////////////////////////////////////
/// partition
//////////////////////////////////////////////////////////////
def process partition(max: number) as "partition{num}" default 1 with
keep prev = 0
prev = if prev >= max then 1 else prev + 1
return prev
//////////////////////////////////////////////////////////////
/// rgb
//////////////////////////////////////////////////////////////
def pure rgb(r : number, g : number, b : number) as "rgb" with
if r < 0 or r > 1 or g < 0 or g > 1 or b < 0 or b > 1
_ = assertfail("Color components must be in [0, 1].")
rr = to.long(r * 255)
gg = to.long(g * 255)
bb = to.long(b * 255)
return "#\{rr:X2}\{gg:X2}\{bb:X2}"
//////////////////////////////////////////////////////////////
/// dispersion
//////////////////////////////////////////////////////////////
def pure dispersion(r : ranvar) as "dispersion" with
mean = mean(r)
variance = variance(r)
if mean <= 0
_ = assertfail("Mean must be strictly greater than 0.")
return variance/mean
//////////////////////////////////////////////////////////////
/// Year start and end dates defined by a month primitive
/// object and a year number.
//////////////////////////////////////////////////////////////
def pure yearStart(y: number) as "yearStart(num)" with
return date(y, 1, 1)
def pure yearStart(m: month) as "yearStart(mnth)" with
return yearStart(date(m, 1))
def pure yearEnd(y: number) as "yearEnd(num)" with
return date(y, 12, 31)
def pure yearEnd(m: month) as "yearEnd(mnth)" with
return yearEnd(date(m, 1))
//////////////////////////////////////////////////////////////
/// sliceUrl overload.
//////////////////////////////////////////////////////////////
def pure sliceUrl(slice : ordinal, tab : text) as "sliceurl(ord,txt)" with
return concat(sliceUrl(slice),"&t=\{tab}")
//////////////////////////////////////////////////////////////
/// fieldCount function.
//////////////////////////////////////////////////////////////
def pure fieldCount(haystack : text, sep : text) as "fieldCount(txt,txt)" with
return if strlen(haystack) == 0 then 0 else containsCount(haystack, sep) + 1
//////////////////////////////////////////////////////////////
// changed function.
//////////////////////////////////////////////////////////////
def process changed(next: number) as "changed{num}" default false with
keep prev = 0
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: date) as "changed{date}" default false with
keep prev = date(2001,1,1)
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: week) as "changed{week}" default false with
keep prev = week(2001,1)
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: month) as "changed{mnth}" default false with
keep prev = month(2001,1)
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: ranvar) as "changed{dist}" default false with
keep prev = dirac(0)
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: zedfunc) as "changed{fun}" default false with
keep prev = linear(0)
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: double) as "changed{dbl}" default false with
keep prev = to.double(0)
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: ordinal) as "changed{ord}" default false with
keep prev = bad_ord__()
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: text) as "changed{text}" default false with
keep prev = ""
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: boolean) as "changed{bool}" default false with
keep prev = false
changed = prev != next
prev = next
return argfirst() or changed
def process changed(next: long) as "changed{long}" default false with
keep prev = to.long(0)
changed = prev != next
prev = next
return argfirst() or changed
//////////////////////////////////////////////////////////////
/// consume function
//////////////////////////////////////////////////////////////
def process consume(qtyAvailable: number; qtyRequested: number) as "consume{number;number}" with
keep leftRequested = qtyRequested
qtyConsumed = min(qtyAvailable, leftRequested)
leftRequested = leftRequested - qtyConsumed
return qtyConsumed