;+ ; PURPOSE: ; This function evaluates, or returns samples drawn at random from, a ; PieceWise Power Law distribution. ; ; CATEGORY: ; Statistics ; ; CALLING SEQUENCE: ; result = pwpl(xs, alphas, x = x, random = random) ; ; INPUTS: ; xmins: A vector specifying the abscissas of the powerlaw boundaries in ; increasing order. These are the lower bounds for each piecewise ; segment. ; alphas: The power law exponents at each of the boundaries ; ; KEYWORD PARAMETERS: ; x: A set of abscissas against which to evaluate the power law ; random: Set to an integer n to return n samples drawn from this distribution ; ; OUTPUTS: ; If x is set, the function returns f(x). If random is set, the ; function returns a set of numbers at random from dN/dx = f(x). ; f(x) is given by the following equation ; dN / dx = Const * x^alpha[i], for x[i] <= x < x[i+1] ; If x < x[0], then dN / dx = 0 ; ; SEE ALSO: ; imf ; ; TODO: ; Implement RANDOM keyword ; ; MODIFICATION HISTORY: ; June 2009: Written by Chris Beaumont ;- function pwpl, xmins, alphas, x = x, random = random compile_opt idl2 ;-on_error, 2 ;- check inputs if n_params() ne 2 then begin print, 'pwpl calling sequence:' print, 'result = pwpl(xmins, alphas x = x, random = random)' return, !values.f_nan endif sz = n_elements(xmins) if n_elements(alphas) ne sz then $ message, 'xmins and alphas are not the same size' if keyword_set(random) then message, $ 'random keyword not yet implemented' if keyword_set(random) && keyword_set(x) then $ message, 'cannot choose both x and random keywords' ;- make sure that xmin is in sorted order shift = shift(xmins, 1) shift[0] = 0 if min(xmins - shift) lt 0 then $ message, 'xmins are not listed in increasing order' if xmins[0] lt 0 then $ message, 'xmins must be positive' ;- make sure that the piecewise power law is normalizeable if alphas[0] le -1 || alphas[sz-1] ge -1 then $ message, 'piecewise power law is not normalizeable' ;- determine scaling exponents for continuity cs = dblarr(sz) + 1 for i = 1, sz-1, 1 do begin if xmins[i-1] eq 0 then cs[i] = cs[i-1] else $ cs[i] = cs[i-1] * (xmins[i] / xmins[i-1])^(alphas[i-1]) endfor ;- determine normalization factor norm = 0D for i = 0, sz-2, 1 do begin if xmins[i] eq 0 then begin norm += cs[i] * (xmins[i+1] - xmins[i]) endif else begin norm += cs[i] / (alphas[i] + 1) * ((xmins[i+1]/xmins[i])^(alphas[i] + 1) - 1) endelse endfor norm -= cs[sz-1] / (alphas[sz-1] + 1) cs /= norm ;- if x keyword is supplied, then evaluate function if n_elements(x) ne 0 then begin result = x * 0 for i = 0, sz - 1, 1 do begin hit = where(x ge xmins[i], ct) if ct eq 0 then continue result[hit] = cs[i] * (x[hit] / xmins[i])^(alphas[i]) endfor return, result endif else begin ;- XXX add this message, 'random sampling form pwpl not yet implemented' endelse end