Means API

+- HP Forums (http://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: HP Prime Software Library (/forum-15.html)
+--- Thread: Means API (/thread-9852.html)



Means API - StephenG1CMZ - 01-04-2018 04:18 AM

Having noticed that some means are not built-in on the Prime (or perhaps I have overlooked them), here is a collection of common means and other numerical list routines.
See also thread: http://www.hpmuseum.org/forum/thread-9757.html


RE: Means API - StephenG1CMZ - 01-04-2018 04:24 AM

Means V0.1
Errors are handled by my List program, which should be compiled first (or comment out error messages).
Don't assume negative values are handled as you wish:

Code:

 
 LOCAL CRID:="Means V0.1 © 2018 StephenG1CMZ"; 
 LOCAL MN:="Means.";
 LOCAL MORETEXT:="A bag of mostly means.";//ST:TNG

 //IMPORT({LIST}); //LIST Handles Error Messages

 LOCAL EMPTY0:=0;//ADDITIVE
 LOCAL EMPTY1:=1;//MULTIPLICATIVE

 //NAN CAN BE GENERATED
 //NONE OF THESE ROUTINES HANDLE NAN IN INPUT LST DATA
 //BUT YOU CAN USE List.IsNumeric to check IF A LIST IS OK

 //ERR 
 LOCAL NaN:="NaN";
 LOCAL ListErrK:=1;//1=SHOW ERROR

 //MLSTRING TO MATCH ML
 LOCAL MLS:={
   "MIN:              ",
   "MIN|:             ",
   "HarmonicMean:     ",
   "GeometricMean:    ",
   "GeometricMeanS:   ",
   "GeometricAverage: ",
   "ArithmeticMean:   ",
   "InterQuartileMean: ",
   "MidRange:          ",
   "RootMeanSquare RMS: ",
   "Cubic:             ",
   "ContraHarmonicMean: ",
   "PowerMean(−1):     ",
   "PowerMean(3):      ", 
   "MAX:               ",
   "MAX|:              " };

 EXPORT ABOUT()
 BEGIN
  MSGBOX(CRID);
  MSGBOX(MORETEXT); 
 END;

 // List math procedures
 // Probably only work on numeric lists

 TBD()
 BEGIN
  MSGBOX("TBD");
 END;

 NAN()
 BEGIN
  RETURN NaN;
 END;

 EMPTIES(ST)
 BEGIN 
  RAISE(MN+ST,EL,ListIsEmptyError,"",ListErrK);
  RAISE(MN+ST,EL,ListStatisticsError,"",ListErrK);
  RETURN NAN();
 END;

 DIVBY0(ST)
 BEGIN 
  RAISE(MN+ST,EL,DivBy0Error,"",ListErrK);
  RAISE(MN+ST,EL,ListStatisticsError,"",ListErrK);
  RETURN NAN();//IN LIEU OF +INF OR −INF
 END;

 EXPORT ListΣLIST(LST)
 BEGIN
  RETURN IFTE(SIZE(LST),ΣLIST(LST),EMPTY0); 
 END;

 EXPORT ListΠLIST(LST)
 BEGIN
  LOCAL SZ:=SIZE(LST);
  
  IF SZ>1 THEN RETURN ΠLIST(LST);
  END;
  IF SZ==1 THEN RETURN LST(1);
  END;
  //IF SZ==0 THEN
  RETURN EMPTY1;
  //END;
 END;

 EXPORT ListCUMSUM(LST)
 //Puzzle #41
 //{}={0}
 BEGIN
  RETURN IFTE(SIZE(LST),cumSum(LST),{0}); 
 END;

 EXPORT ListMAX(LST)
 BEGIN
  RETURN IFTE(SIZE(LST),MAX(LST),EMPTY0);
 END;

 EXPORT ListMAXABS(LST)
 //MAX MAGNITUDE IGNORING SIGN
 //
 BEGIN
  RETURN  MAX(ListMAX(LST),−ListMIN(LST));
 END;

 EXPORT ListMEAN(LST)
 BEGIN
  IF SIZE(LST) THEN
   RETURN (mean(LST));
  END;
  RETURN EMPTIES("");
 END;
 //NB MEAN AND MEAN2 CURRENTLY RETURN TYPE RAT
 //USE approx if you prefer real
 EXPORT ListMEAN2(LSTV,LSTF)
 BEGIN
  IF SIZE(LSTV) AND SIZE(LSTF) THEN
   RETURN (mean(LSTV,LSTF));
  END;  
  RETURN EMPTIES("");
 END;
 //MEDIAN
 EXPORT ListMIN(LST)
 BEGIN
  RETURN IFTE(SIZE(LST),MIN(LST),EMPTY0);
 END;

 EXPORT ListMINABS(LST)
 BEGIN
  IF SIZE(LST) THEN
   RETURN MIN(ABS(LST));
  END;
  RETURN 0;
 END;

 //MODE

 EXPORT ArithmeticMean(LST)
 BEGIN
  RETURN ListMEAN(LST);
 END;

 EXPORT ContraHarmonicMean(LST)
 //POSITIVE LST
 BEGIN
  LOCAL DEN:=ListΣLIST(LST);
 
  IF SIZE(LST) THEN
   IF DEN THEN
    RETURN ListΣLIST(LST^2)/DEN;
   ELSE
    RETURN DIVBY0("");
   END;  
  END;
  RETURN EMPTIES(""); 
 END;

EXPORT CubicMean (LST)
 BEGIN
  LOCAL NN:=SIZE(LST);
  IF NN THEN
   RETURN approx(surd(((ListΣLIST(LST^3))/NN),3));
  END;
  RETURN EMPTIES("");
 END;

 GeometricAverage(LST)
 //AVERAGE GROWTH FROM LST(1) TO LST(0) IN NN STEPS.
 //NB INTERMEDIATE VALUES ARE NOT REFERENCED
 //BUT SIZE OF LST IS
 BEGIN
  LOCAL AZ,AN;
  LOCAL NNN:=SIZE(LST)-1;//BECAUSE 1.N NOT 0.N
  IF NNN>0 THEN
   AZ:=LST(1);
   IF AZ THEN
    AN:=LST(SIZE(LST));
    RETURN (AN/AZ)^(1/NNN);
   ELSE
    RETURN DIVBY0("");
   END;
  END;
  RETURN EMPTIES("");
 END;

 EXPORT GeometricMean(LST)
 //Geometric mean
 //Positive (not checked)
 //ANY 0:0
 //Products can overflow:See GMeanS
 BEGIN
  LOCAL NN:=SIZE(LST);
  IF NN THEN 
   //using surd instead of ^1/N avoids <0FAIL
   //negatives may yield imaginary mean
   RETURN approx(surd(ListΠLIST(LST),NN));
  END;
  RETURN EMPTIES("");
 END;

 //NB WHEN NEGATIVES ARE PRESENT
 //GMEAN AND GMEANS YIELD DIFFERING RESULTS
 //VERIFY?

 EXPORT GeometricMeanS(LST)
 //SLOW VERSION USES LOGS TO AVOID OVERFLOW
 //SO ABS TO AVOID NEGATIVES
 //ANY 0=0 AS GMEAN
 BEGIN
 LOCAL MULT,SIGNLST;
 LOCAL NN:=SIZE(LST);
 IF NN THEN
  IF POS(LST,0) THEN
   RETURN 0;
  END;
  //MULTIPLY NEGATIVES TBC
  //RECOMMENDED: MULT=(−1)^(MM/NN): MM=COUNT NEGATIVES
  //TO AVOID COUNTING  MM I THINK MULTIPLYING ALL SIGNS MAY BE QUICKER 
  //TBC
  SIGNLST:=SIGN(LST);
  MULT:=IFTE(POS(SIGNLST,−1),ListΠLIST(SIGNLST),1);//COULD JUST MULTIPLY ALWAYS
 
  //EITHER LOG COULD BE USED
  RETURN MULT*e^(ListΣLIST(LN(ABS(LST)))/NN);
 END;
 RETURN EMPTIES("");
 END;

 EXPORT HarmonicMean(LST)
 //Positive preferred
 //EG(1,−1)=/0=NAN
 BEGIN
  LOCAL NN:=SIZE(LST);
  LOCAL DEN;
  IF NN THEN
   IF POS(LST,0) THEN
    RETURN 0;//ANY 0=0
   END;
   DEN:=ΣLIST(1/LST);//0 UNEXPECTED:UNDERFLOW?=INF MEAN
   RETURN IFTE(DEN,SIZE(LST)/DEN,NAN());//GUARD 0 DEN
  END; 
  RETURN EMPTIES("");
 END;

 EXPORT InterQuartileMean (SORTEDLST)
 //InterQuartileMean:List must be sorted
 //TBC
 //DO THE SLICE INDICES NEED CASTING TO INT
 //IF SO ROUND OR TRUNC?
 //THIS IMPLEMENT IS ONLY CORRECT IF THE SIZE IS DIVISBLE BY 4
 //TBC
 BEGIN
  LOCAL NN:=SIZE(SORTEDLST);
  IF SIZE(SORTEDLST)≥4 THEN
   RETURN (2/NN)*ListΣLIST(SORTEDLST({(NN/4)+1,(3*NN/4)}));
  END;
  //SMALL LIST: FALLBACK TO MEAN
  RETURN ArithmeticMean(SORTEDLST);//In this case it neednt be
 END;

 EXPORT InterQuartileMeanL(LST)
 //This temporary version also works if not divisible by 4
 //But is inefficient
 //It is not recommended
 BEGIN
  LOCAL NN:=SIZE(LST);
  //MAKE LST 4 TIMES BIGGER INSTEAD:MAY FAIL
  LOCAL TMP;
  TMP:=CONCAT(LST,LST);
  TMP:=CONCAT(TMP,LST);
  TMP:=CONCAT(TMP,LST);
  TMP:=SORT(TMP);
  RETURN (ArithmeticMean(TMP({NN+1,3*NN})));
 END;

 EXPORT MidRange(LST)
 BEGIN
  //MSGBOX("MID");
  RETURN (ListMAX(LST)+ListMIN(LST))/2;
 END;
 
EXPORT PowerMean (LST,PWR)
 //AKA GeneralisedMean
 //PWR:REAL NONZERO
 //LST:POSITIVE SO ABS
 //IMPLEMENT MAY DIFFER FROM CUBIC ETC
 BEGIN
  LOCAL NN:=SIZE(LST);
  IF NN THEN
   RETURN IFTE(PWR,approx(surd(((ListΣLIST(ABS(LST)^(PWR)))/NN),PWR)),DIVBY0("")); 
  END;
  RETURN EMPTIES("");
 END;

 EXPORT RMS(LST)
 BEGIN
  LOCAL NN:=SIZE(LST);
  IF NN THEN
   RETURN √((ListΣLIST(LST^2))/NN);
  END;
  RETURN EMPTIES("");
 END;

 EXPORT RootMeanSqare(LST)
 BEGIN
  RETURN RMS(LST);
 END;

 EXPORT TruncatedMean(LST)
 //EXCLUDE EXTREMES
 BEGIN
  TBD();
 END;
 //SPECIFY A PERCENTAGE OR SIMILAR TO EXCLUDE
 EXPORT WinsorisedMean(LST)
 //A VARIATION OF TRUNCATED:CLAMP EXTREMES
 //There is an implementation in the library
 BEGIN
  TBD();
 END;

 EXPORT ManyMeans(LST)
 //WHAT NUMBER DID YOU WANT? :)
 BEGIN
  LOCAL SAVED:=ListShowErrors;
  LOCAL ML:={};
  //SEQUENCE TO MATCH MLS
  ListShowErrors:=0;
  ML:={
   ListMIN(LST),
   ListMINABS(LST),
   HarmonicMean(LST),
   GeometricMean(LST),
   GeometricMeanS(LST),
   GeometricAverage(LST),
   ArithmeticMean(LST),
   InterQuartileMean(SORT(LST)),
   MidRange(LST),
   RMS(LST),
   CubicMean(LST),
   ContraHarmonicMean(LST),
   PowerMean(LST,−1),
   PowerMean(LST,3),
   ListMAX(LST),
   ListMAXABS(LST) };

  ListShowErrors:=SAVED;
  RETURN ML;
 END;
  
 EXPORT ManyMeansCHS(LST)
 BEGIN
  LOCAL II,TM,CHS;
  LOCAL ML:={};
  LOCAL RLST;

  //PRINT(MN+" SIZE: "+SIZE(LST));//SIZE WARNS OF POSSIBLE SLOW CALCS
  TM:=TEVAL(ML:=ManyMeans(LST));//TIMED CALCULATION
  RLST:=MAKELIST((MLS(II)+ML(II)),II,1,SIZE(MLS));
  CHOOSE(CHS,CRID,RLST);
  //PRINT("Used "+TM);//Performance.And confirms list completed.
 END;

 EXPORT ManyMeansPRINT(LST)
 BEGIN
  LOCAL II,TM;
  LOCAL ML:={};

  PRINT();
  PRINT(CRID);
  PRINT(MN+" SIZE: "+SIZE(LST));//SIZE WARNS OF POSSIBLE SLOW CALCS
  TM:=TEVAL(ML:=ManyMeans(LST));//TIMED CALCULATION
  
  FOR II FROM 1 TO SIZE(MLS) DO
   PRINT(MLS(II)+ML(II));
  END;
  PRINT("Used "+TM);//Performance.And confirms list completed.
 END;

 EXPORT IsMEAN(LST,XX,PWR)
 //Is XX a possible mean
 //First exact match
 BEGIN
  LOCAL ML:=ManyMeans(LST);

  RETURN POS(ML,XX);
 END;

 EXPORT IsNAN(LST)
 BEGIN
  MSGBOX(MN+"IsNAN\nUse StephenG1CMZ's List.IsNUMERIC");
  RETURN 0;
 END;

EXPORT MeansSeeAlso ()
 BEGIN
  LOCAL KK;
  LOCAL CatFuns:={
   "cumSum",
   "deltalist",
   "max",
   "mean",
   "min",
   "product",
   "trunc"};
  //Just Listed as a reminder:not Selectable
  CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)

 END;

 EXPORT MEANS()
 BEGIN
  //DIVBY0("");//TEST
 END;