macro
bootmean x1;
  nullmean mu_o;
  conlevel cil;
  times B;
  examples;
  storavgs x4.

mconstant B n i mu_o D_o cil le_pval ge_pval pval2
mconstant alpha2 L L1 L2 lower upper current answer
mcolumn x1 x2 x3 x4 x5
mcolumn c100 c101 c102 c103 c104 c105 c106 c107 c108 c109
default B=5000 mu_o=0

plug

# compute resample means and sort
if nullmean = 1 | conlevel = 1 | storavgs = 1
  copy x1 x5;
    omit x1 = '*'.
  let n=count(x5) 
  if n < 10
    note
    note    Bootmean is exiting because your sample size is less than 10.
    note    The bootstrap method used by this program requires sample sizes
    note    of at least 10 to provide reliable confidence intervals and p-values.
    note
    exit
  endif
  do i=1:B 
    sample n x5 x2; 
      replace. 
    let x3(i)=mean(x2) 
  enddo 
  sort x3 x3;
  by x3.
elseif examples = 0
  note
  note   Bootmean is exiting because no computations were requested.
  note   To request a computation use the nullmean,
  note   conlevel, or storavgs subcommand.  For a list of
  note   examples, use the following command:
  note    
  note     %bootmean c1;
  note       examples.
  note
  exit
endif  

# hypothesis tests requested; compute p-values
if nullmean = 1

  # compute le_pval
  let i = B
  while x3(i) > mu_o
    let i = i - 1
  endwhile 
  let le_pval = (B-i)/B

  # compute ge_pval
  let i = 1
  while x3(i) < mu_o
    let i = i + 1
  endwhile
  let ge_pval = (i-1)/B

  # compute 2-sided pvalue, pval2
  if le_pval < ge_pval
    let pval2 = 2*le_pval
  else
    let pval2 = 2*ge_pval
  endif

  note
  note Bootmean hypothesis testing results:

  let c100 = "  P-value for testing H_0: mu = "
  copy mu_o c101
  text c101 c102
  let c103 = " versus H_a: mu < "
  copy mu_o c104
  text c104 c105
  let c106 = " is "
  copy le_pval C107
  text c107 c108;
    significant 4.
  concatenate c100 C102 C103 C105 C106 C108 c109
  write c109;
    text;
  file 'TERMINAL'.

  let c100 = "  P-value for testing H_0: mu = "
  copy mu_o c101
  text c101 c102
  let c103 = " versus H_a: mu > "
  copy mu_o c104
  text c104 c105
  let c106 = " is "
  copy ge_pval C107
  text c107 c108;
    significant 4.
  concatenate c100 C102 C103 C105 C106 C108 c109
  write c109;
    text;
  file 'TERMINAL'.
 

  let c100 = "  P-value for testing H_0: mu = "
  copy mu_o c101
  text c101 c102
  let c103 = " versus H_a: mu NOT equal to "
  copy mu_o c104
  text c104 c105
  let c106 = " is "
  copy pval2 C107
  text c107 c108;
    significant 4.
  concatenate c100 C102 C103 C105 C106 C108 c109
  write c109;
    text;
  file 'TERMINAL'.
    
    
endif

# confidence interval requested; compute it.
if conlevel = 1

  # compute lower endpoint of CI
  let alpha2 = (100 - cil)/200
  let L = round(alpha2*B)
  if L/B <= alpha2
    let L1 = L
    let L2 = L + 1
  else
    let L1 = L - 1
    let L2 = L
  endif

  # get indices for jumps in empirical distn. fn.
  # find index of first value less than x3(L2)
  if x3(L1) = x3(L2)
    let current = x3(L1)
    let i = L1 - 1
    while x3(i) = current
      let i = i - 1
    endwhile
    let L1 = i
  endif

  # find largest index of values equal to x3(L2)
  let current = x3(L2)
  let i = L2
  while x3(i) = current
    let i = i + 1
  endwhile
  let L2 = i - 1

  # linearly interpolate lower endpoint of CI
  let lower = (B*alpha2 - L1)/(L2 - L1)*(x3(L2)-x3(L1))+x3(L1)

  # compute upper endpoint of CI using same procedure
  # used for lower endpoint but with different alpha2
  let alpha2 = 1 - alpha2
  let L = round(alpha2*B)
  if L/B <= alpha2
    let L1 = L
    let L2 = L + 1
  else
    let L1 = L - 1
    let L2 = L
  endif

  # get indices for jumps in empirical distn. fn.
  # find index of first value less than x3(L2)
  if x3(L1) = x3(L2)
    let current = x3(L1)
    let i = L1 - 1
    while x3(i) = current
      let i = i - 1
    endwhile
    let L1 = i
  endif

  # find largest index of values equal to x3(L2)
  let current = x3(L2)
  let i = L2
  while x3(i) = current
    let i = i + 1
  endwhile
  let L2 = i - 1

  # linearly interpolate upper endpoint of CI
  let upper = (B*alpha2 - L1)/(L2 - L1)*(x3(L2)-x3(L1))+x3(L1)

  # output result 

  let c100 = "Bootmean "
  copy  cil c101
  text c101 c102
  let c103 = "% confidence interval for mu: ( "
  copy lower c101
  text c101 c104;
    significant 4.
  let c105 = ", "
  copy upper c101
  text c101 c106;
    significant 4.
  let c107 = " )"
  concatenate c100 c102 c103 c104 c105 c106 c107 c108 
  write c108;
    file 'TERMINAL'.
    
endif

if storavgs = 1
  copy x3 x4
endif

if examples = 1
  note   
  note  Bootmean examples:
  note
  note  To test a hypothesis concerning the
  note  population mean mu using data in c8
  note  with mu_o = 2, use bootmean with the
  note  'nullmean' subcommand as follows:
  note
  note     %bootmean c8;
  note        nullmean 2.
  note
  note  Note that the 'nullmean' subcommand is used
  note  to specify the value of mu_o.
  note
  note  Continue with a confidence interval example (y/n)?
  yesno answer
  if answer = 0
    exit
  endif
  note  To compute a 95% confidence interval for
  note  mu using data in c8, call bootmean with
  note  'conlevel' subcommand as follows:
  note  
  note     %bootmean c8;
  note        conlevel 95.
  note
  note  Note that the 'conlevel' subcommand is used
  note  to specify the confidence level of the CI.
  note
  note  Continue (y/n)?
  yesno answer
  if answer = 0
    exit
  endif
  note
  note  As with any Minitab macro, you can use multiple
  note  subcommands with bootmean simultaneously, e.g.,
  note
  note     %bootmean c8;
  note        nullmean 2;
  note        conlevel 95.
  note
  note  Note that the multiple subcommands are separated
  note  by semicolons with the final subcommand ended by
  note  a period.
  note
  note  Would you like full list of bootmean subcommands (y/n)?
  yesno answer
  if answer = 0
    exit
  endif
  note
  note  Full syntax for bootmean:
  note
  note     %bootmean c1;
  note        nullmean k1,
  note        conlevel k2,
  note        times k3,
  note        examples,
  note        storavgs c2.
  note
  note   The 'times' subcommand allows you to change the
  note   number of resamples used from 5000 to k3.
  note
  note   The 'storavgs' subcommand allows you to store the
  note   the means from all the resamples (sorted in ascending
  note   order) in the specified column, here c2.
  note
endif

endmacro