text:
const hermite_nodes_sorted = (
    [0.0],
    [-1.7320508075688772, 0.0, 1.7320508075688772],
    [-4.184956017672732, -2.861279576057058, -1.7320508075688772, -0.7410953499945409, 0.0, 0.7410953499945409, 1.7320508075688772, 2.861279576057058, 4.184956017672732],
    [-6.36339449433637, -5.187016039913656, -4.184956017672732, -3.2053337944991944, -2.861279576057058, -2.5960831150492023, -1.7320508075688772, -1.230423634027306, -0.7410953499945409, 0.0, 0.7410953499945409, 1.230423634027306, 1.7320508075688772, 2.5960831150492023, 2.861279576057058, 3.2053337944991944, 4.184956017672732, 5.187016039913656, 6.36339449433637],
    [-9.016939789890303, -7.980771798590561, -7.122106700804617, -6.36339449433637, -5.69817776848811, -5.187016039913656, -4.736433085952297, -4.184956017672732, -3.6353185190372783, -3.2053337944991944, -2.861279576057058, -2.5960831150492023, -2.2336260616769414, -1.7320508075688772, -1.230423634027306, -0.7410953499945409, -0.2489922975799606, -0.0, 0.2489922975799606, 0.7410953499945409, 1.230423634027306, 1.7320508075688772, 2.2336260616769414, 2.5960831150492023, 2.861279576057058, 3.2053337944991944, 3.6353185190372783, 4.184956017672732, 4.736433085952297, 5.187016039913656, 5.69817776848811, 6.36339449433637, 7.122106700804617, 7.980771798590561, 9.016939789890303],
    [-17.495495153554042, -16.649982728342465, -15.95172347567833, -15.329911676699757, -14.757523293637806, -14.220645111085835, -13.710939999150176, -13.222922032153331, -12.752743964706854, -12.29758106590865, -11.855287827274097, -11.424193973821529, -11.002978530773934, -10.59059250398148, -10.18621775676102, -9.789263916781303, -9.39943034111974, -9.016939789890303, -8.643408075750694, -8.286041271175137, -7.980771798590561, -7.754245565035145, -7.460615246780398, -7.122106700804617, -6.790949219291892, -6.5728832710508875, -6.36339449433637, -6.03708487652466, -5.69817776848811, -5.3650910358865325, -5.187016039913656, -5.032018578100965, -4.736433085952297, -4.465863414591742, -4.184956017672732, -3.879171860077358, -3.6353185190372783, -3.520661370177858, -3.2053337944991944, -2.861279576057058, -2.6592875495020794, -2.5960831150492023, -2.2336260616769414, -1.9169487826004017, -1.7320508075688772, -1.534955281503276, -1.230423634027306, -0.944149534001575, -0.7410953499945409, -0.5185674009998361, -0.2489922975799606, 0.0, 0.2489922975799606, 0.5185674009998361, 0.7410953499945409, 0.944149534001575, 1.230423634027306, 1.534955281503276, 1.7320508075688772, 1.9169487826004017, 2.2336260616769414, 2.5960831150492023, 2.6592875495020794, 2.861279576057058, 3.2053337944991944, 3.520661370177858, 3.6353185190372783, 3.879171860077358, 4.184956017672732, 4.465863414591742, 4.736433085952297, 5.032018578100965, 5.187016039913656, 5.3650910358865325, 5.69817776848811, 6.03708487652466, 6.36339449433637, 6.5728832710508875, 6.790949219291892, 7.122106700804617, 7.460615246780398, 7.754245565035145, 7.980771798590561, 8.286041271175137, 8.643408075750694, 9.016939789890303, 9.39943034111974, 9.789263916781303, 10.18621775676102, 10.59059250398148, 11.002978530773934, 11.424193973821529, 11.855287827274097, 12.29758106590865, 12.752743964706854, 13.222922032153331, 13.710939999150176, 14.220645111085835, 14.757523293637806, 15.329911676699757, 15.95172347567833, 16.649982728342465, 17.495495153554042]
)
const hermite_nodes = (
    [0.0],
    [-1.7320508075688772, 0.0, 1.7320508075688772],
    [-4.184956017672732, -2.861279576057058, -0.7410953499945409, -1.7320508075688772, 0.0, 1.7320508075688772, 0.7410953499945409, 2.861279576057058, 4.184956017672732],
    [-6.36339449433637, -5.187016039913656, -3.2053337944991944, -2.5960831150492023, -1.230423634027306, -4.184956017672732, -2.861279576057058, -0.7410953499945409, -1.7320508075688772, 0.0, 1.7320508075688772, 0.7410953499945409, 2.861279576057058, 4.184956017672732, 1.230423634027306, 2.5960831150492023, 3.2053337944991944, 5.187016039913656, 6.36339449433637],
    [-9.016939789890303, -7.980771798590561, -7.122106700804617, -5.69817776848811, -4.736433085952297, -3.6353185190372783, -2.2336260616769414, -0.2489922975799606, -6.36339449433637, -5.187016039913656, -3.2053337944991944, -2.5960831150492023, -1.230423634027306, -4.184956017672732, -2.861279576057058, -0.7410953499945409, -1.7320508075688772, 0.0, 1.7320508075688772, 0.7410953499945409, 2.861279576057058, 4.184956017672732, 1.230423634027306, 2.5960831150492023, 3.2053337944991944, 5.187016039913656, 6.36339449433637, 0.2489922975799606, 2.2336260616769414, 3.6353185190372783, 4.736433085952297, 5.69817776848811, 7.122106700804617, 7.980771798590561, 9.016939789890303],
    [-17.495495153554042, -16.649982728342465, -15.95172347567833, -15.329911676699757, -14.757523293637806, -14.220645111085835, -13.710939999150176, -13.222922032153331, -12.752743964706854, -12.29758106590865, -11.855287827274097, -11.424193973821529, -11.002978530773934, -10.59059250398148, -10.18621775676102, -9.789263916781303, -9.39943034111974, -8.643408075750694, -8.286041271175137, -7.754245565035145, -7.460615246780398, -6.790949219291892, -6.5728832710508875, -6.03708487652466, -5.3650910358865325, -5.032018578100965, -4.465863414591742, -3.879171860077358, -3.520661370177858, -2.6592875495020794, -1.9169487826004017, -1.534955281503276, -0.944149534001575, -0.5185674009998361, -9.016939789890303, -7.980771798590561, -7.122106700804617, -5.69817776848811, -4.736433085952297, -3.6353185190372783, -2.2336260616769414, -0.2489922975799606, -6.36339449433637, -5.187016039913656, -3.2053337944991944, -2.5960831150492023, -1.230423634027306, -4.184956017672732, -2.861279576057058, -0.7410953499945409, -1.7320508075688772, 0.0, 1.7320508075688772, 0.7410953499945409, 2.861279576057058, 4.184956017672732, 1.230423634027306, 2.5960831150492023, 3.2053337944991944, 5.187016039913656, 6.36339449433637, 0.2489922975799606, 2.2336260616769414, 3.6353185190372783, 4.736433085952297, 5.69817776848811, 7.122106700804617, 7.980771798590561, 9.016939789890303, 0.5185674009998361, 0.944149534001575, 1.534955281503276, 1.9169487826004017, 2.6592875495020794, 3.520661370177858, 3.879171860077358, 4.465863414591742, 5.032018578100965, 5.3650910358865325, 6.03708487652466, 6.5728832710508875, 6.790949219291892, 7.460615246780398, 7.754245565035145, 8.286041271175137, 8.643408075750694, 9.39943034111974, 9.789263916781303, 10.18621775676102, 10.59059250398148, 11.002978530773934, 11.424193973821529, 11.855287827274097, 12.29758106590865, 12.752743964706854, 13.222922032153331, 13.710939999150176, 14.220645111085835, 14.757523293637806, 15.329911676699757, 15.95172347567833, 16.649982728342465, 17.495495153554042]
)

const hermite_nodes_diffs = (
    [0.0],
    [-1.7320508075688772, 1.7320508075688772],
    [-4.184956017672732, -2.861279576057058, -0.7410953499945409, 0.7410953499945409, 2.861279576057058, 4.184956017672732],
    [-6.36339449433637, -5.187016039913656, -3.2053337944991944, -2.5960831150492023, -1.230423634027306, 1.230423634027306, 2.5960831150492023, 3.2053337944991944, 5.187016039913656, 6.36339449433637],
    [-9.016939789890303, -7.980771798590561, -7.122106700804617, -5.69817776848811, -4.736433085952297, -3.6353185190372783, -2.2336260616769414, -0.2489922975799606, 0.2489922975799606, 2.2336260616769414, 3.6353185190372783, 4.736433085952297, 5.69817776848811, 7.122106700804617, 7.980771798590561, 9.016939789890303],
    [-17.495495153554042, -16.649982728342465, -15.95172347567833, -15.329911676699757, -14.757523293637806, -14.220645111085835, -13.710939999150176, -13.222922032153331, -12.752743964706854, -12.29758106590865, -11.855287827274097, -11.424193973821529, -11.002978530773934, -10.59059250398148, -10.18621775676102, -9.789263916781303, -9.39943034111974, -8.643408075750694, -8.286041271175137, -7.754245565035145, -7.460615246780398, -6.790949219291892, -6.5728832710508875, -6.03708487652466, -5.3650910358865325, -5.032018578100965, -4.465863414591742, -3.879171860077358, -3.520661370177858, -2.6592875495020794, -1.9169487826004017, -1.534955281503276, -0.944149534001575, -0.5185674009998361, 0.5185674009998361, 0.944149534001575, 1.534955281503276, 1.9169487826004017, 2.6592875495020794, 3.520661370177858, 3.879171860077358, 4.465863414591742, 5.032018578100965, 5.3650910358865325, 6.03708487652466, 6.5728832710508875, 6.790949219291892, 7.460615246780398, 7.754245565035145, 8.286041271175137, 8.643408075750694, 9.39943034111974, 9.789263916781303, 10.18621775676102, 10.59059250398148, 11.002978530773934, 11.424193973821529, 11.855287827274097, 12.29758106590865, 12.752743964706854, 13.222922032153331, 13.710939999150176, 14.220645111085835, 14.757523293637806, 15.329911676699757, 15.95172347567833, 16.649982728342465, 17.495495153554042]
)

const hermite_nodes_posi_diffs = (
    [0.0],
    [1.7320508075688772],
    [0.7410953499945409, 2.861279576057058, 4.184956017672732],
    [1.230423634027306, 2.5960831150492023, 3.2053337944991944, 5.187016039913656, 6.36339449433637],
    [0.2489922975799606, 2.2336260616769414, 3.6353185190372783, 4.736433085952297, 5.69817776848811, 7.122106700804617, 7.980771798590561, 9.016939789890303],
    [0.5185674009998361, 0.944149534001575, 1.534955281503276, 1.9169487826004017, 2.6592875495020794, 3.520661370177858, 3.879171860077358, 4.465863414591742, 5.032018578100965, 5.3650910358865325, 6.03708487652466, 6.5728832710508875, 6.790949219291892, 7.460615246780398, 7.754245565035145, 8.286041271175137, 8.643408075750694, 9.39943034111974, 9.789263916781303, 10.18621775676102, 10.59059250398148, 11.002978530773934, 11.424193973821529, 11.855287827274097, 12.29758106590865, 12.752743964706854, 13.222922032153331, 13.710939999150176, 14.220645111085835, 14.757523293637806, 15.329911676699757, 15.95172347567833, 16.649982728342465, 17.495495153554042]
)

const hermite_weights = (
    [2.50662827463100068570156508940272033214569091796875000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000],[4.17771379105166780950260848233781112584839021831128398395845655420277136973850518985113985470368122612393154707094673772781137374347013528936971656617452929e-01, -4.19237097478076970438745693719410311863549603819822390764094825262801951651394452982470507593459469805441031086415250901127088887538832399995942598759339798e-17, 1.67108551642066712380104339293515810697601287430649320320830868915944572605229896202977202905926375477521369058581065245443772525130597294212605668676509414, 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 4.17771379105166780950260848233781112584839021831128398395845655420277136973850518985113985470368122612393154707094673772781137374347013528936971656617453153e-01, 4.19237097478076970438745693719410311863549603819822390764094825262801951651394452982470507593459469805441031086415250901127088887538832398877191489079308786e-17],[-7.07501097658322454199390379584851025435894425241697536328837939292120218354250054599102042294141837267286811486089855108234705864387368706471620650956051348e-06, -5.51516957239086212373432126614411911693191126942228897459266351941847350217083855933438059078397715499485455939928041586896260031814228159940667754175159504e-05, -1.13334180863541629364197791796535260542897127807854713116806843050716873960848010199200775478915063998747603405014385232799876192676569055430283284541897099e-03, -6.66593558897620685488385163387736286029740429637896422663954787544700628710726215223510503110734340541981431013634890785363646618588313913156400091715725646e-03, 1.95847769432570015787706869904356609014399287570505626924963443637672194091341572393368048935420510250235047960366040947487605183842722584559344472374635837e-01, -5.19421731950808398650327897313391534999219139365278195708071399927888884148148349414462466457725160901305042552331593861433507458190942525224390814810845563e-01, -2.36200259318188695511717365225205321815209840356408365541582522550852995285182999451091061066230110921309429567437936004705158599060581452487342644770777685e-02, -1.20528465958547754046527997451807072426229275438974780246267591229369843244088402400364767540373101009750894623416389045739065502681551496484387982745232319e-01, 2.16445362126872239226486276628257058071130097134368234747145233085462639075793750030855811189282918580051208779708551480772398357009749024986151468280244218, 4.11930615771558047862609067663424724721358503359634387187443007358545148885545242464189564626400262092652776466095935622600091695687932183623363836835623732e-148, -2.36200259318188695511717365225205321815209840356408365541582522550852995285182999451091061066230110921309429567437936004705158599060581452487342644372382957e-02, 1.20528465958547754046527997451807072426229275438974780246267591229369843244088402400364767540373101009750894623416389045739065502681551496484387982720810728e-01, 1.95847769432570015787706869904356609014399287570505626924963443637672194091341572393368048935420510250235047960366040947487605183842722584559344472161780759e-01, 5.19421731950808398650327897313391534999219139365278195708071399927888884148148349414462466457725160901305042552331593861433507458190942525224390814638081751e-01, -1.13334180863541629364197791796535260542897127807854713116806843050716873960848010199200775478915063998747603405014385232799876192676569055430283284550653191e-03, 6.66593558897620685488385163387736286029740429637896422663954787544700628710726215223510503110734340541981431013634890785363646618588313913156400091837516621e-03, -7.07501097658322454199390379584851025435894425241697536328837939292120218354250054599102042294141837267286811486089855108234705864387368706471620647507850662e-06, 5.51516957239086212373432126614411911693191126942228897459266351941847350217083855933438059078397715499485455939928041586896260031814228159940667754183588012e-05],[-8.69924646291661497327337925822803207013312470111070900140022199586885341674426816341989526940113793289433151087580624834057553598198107174306641319636279303e-09, -1.51885572096044300377947592275024997407945601381203266920202927715739608225772195905177693406054956682305560951014528376736207469902959358750304583551839663e-09, -2.25083069088309843249053776369919336205779570892564788445729202363676572562695442224118641963003176894893285531916154143399882055416168956333169753393142316e-05, -3.66934302029247598134991778142388369433921108276087652062779374772382252510866022335759386106176321785959149065891987805029348587755863595297063110939388468e-06, -6.55119715312103369330759813658483173146990324122461775521553370279341359210446670299496235514383811447251499744940367450464198514416864906228731773298062944e+01, -5.544441804367122728886371832947345495647259160964632860324868040712634113289335659916238351213134877110799595515034108873067827780817537581027735037535471, 6.20646429465336567666879994557457026743771624156876262589235596645487862436968496665408785581354728426835910244302405580223730657474423843228278434356868396e+02, -1.29277740938337702162991692490197537994933621134945860367079954135060086522980930342214854473670232794145515701794435323118281955964214588830103082820330039e+02, -2.32961360387237720516779068306749134347258145943687622787261360329903002887868986013127505759009139693672132508112420431304192521347508079809299649109077584e+02, -4.67455713778865780356436962927923799575314370712991471136017088588074274216352144611979502965884933013256654177670572050117006287050494701930971618869917412e+02, -1.42414417735928155313623854468288337087502080068209912154174244035552906641457299235465137034584745621770659395221345419145265663460473421721071028030911985e-02, -2.19311756409373396671635423503146984815925768025106734842273300799390695469442091764502327446199602437218938511700420291914689094313155033401660584602476692e-03, -6.29810049957154362982644381421613767017453487523667725814109895477386630370537176307757028521586624149223699556307018040419006073013378064160524467017431895e+02, -1.01234973262020206467745162909414578657262396479877132130805644096973409495163679514882515969716507994938001019356614399447030653831816379641656410339013698e+02, 8.43238831025022137706958965502123950898109730620092973632021517702453530587218043132187763838788978524062602474423802754036833152199929932834222613990643189e+02, -2.67929766424201838469801636988509271032298152582110614839833139102454723942760694025365720332128448291215582190044014037388839024433762616568002794537106503e+02, -6.46464140837993263354271496841064060446113427125272971787304539434901398361951360899494392350469821590505678729828480238797419293795755135928077257302740265e+02, -1.85684829681906347565462546556352050817895558009377575030906544956262762483619740889945664827014582807278644399683072728973983171995463019017305403519433316e+02, 2.24259680638664453730430105368987013467171973085973343336757977841815576342811811737888075702695619343018305076356307916679218089638202215755508261083263191e+02, -8.13330267275235780996462378898983586862571993581053449028873579872680593586098163873756414455520044191920900466073778472286014436788087855971312175780420956e-135, -6.46464140837993263354271496841064060446113427125272971787304539434901398361951360899494392350469821590505678729828480238797419293795755107279444910793215062e+02, 1.85684829681906347565462546556352050817895558009377575030906544956262762483619740889945664827014582807278644399683072728973983171995463012228992526306921475e+02, 8.43238831025022137706958965502123950898109730620092973632021517702453530587218043132187763838788978524062602474423802754036833152199929888544756108194972754e+02, 2.67929766424201838469801636988509271032298152582110614839833139102454723942760694025365720332128448291215582190044014037388839024433762590920781485666858641e+02, -6.29810049957154362982644381421613767017453487523667725814109895477386630370537176307757028521586624149223699556307018040419006073013378052097841856483431224e+02, 1.01234973262020206467745162909414578657262396479877132130805644096973409495163679514882515969716507994938001019356614399447030653831816377877898220857671902e+02, -1.42414417735928155313623854468288337087502080068209912154174244035552906641457299235465137034584745621770659395221345419145265663460473420517338795121267543e-02, 2.1931175640937339667163542350314698481592576802510673484227330079939069546944209176450232744619960243721893851170042029191468909431315503173536846262369399e-03, -2.32961360387237720516779068306749134347258145943687622787261360329903002887868986013127505759009139693672132508112420431304192521347508043081102490052478411e+02, 4.67455713778865780356436962927923799575314370712991471136017088588074274216352144611979502965884933013256654177670572050117006287050494676177498541824440793e+02, 6.20646429465336567666879994557457026743771624156876262589235596645487862436968496665408785581354728426835910244302405580223730657474423832142044295785188488e+02, 1.29277740938337702162991692490197537994933621134945860367079954135060086522980930342214854473670232794145515701794435323118281955964214586175770671118093615e+02, -6.55119715312103369330759813658483173146990324122461775521553370279341359210446670299496235514383811447251499744940367450464198514416864896505597400799885802e+01, 5.54444180436712272888637183294734549564725916096463286032486804071263411328933565991623835121313487711079959551503410887306782778081753750281754740869787893, -2.25083069088309843249053776369919336205779570892564788445729202363676572562695442224118641963003176894893285531916154143399882055416168955326363642931576091e-05, 3.66934302029247598134991778142388369433921108276087652062779374772382252510866022335759386106176321785959149065891987805029348587755863593917387038326550394e-06, -8.69924646291661497327337925822803207013312470111070900140022199586885341674426816341989526940113793289433151087580624834057553598198107172522048769573338537e-09, 1.51885572096044300377947592275024997407945601381203266920202927715739608225772195905177693406054956682305560951014528376736207469902959358526961821438794155e-09],[-3.53840266519784534634346236572959466490796755936423589303096581589894522900429548295704949921034363841097016014084820543166784150709455482641633290258751226e-17, -3.63650949219797153077026801871288631022589877099722369182283745957504622255018333946848480082306165027448314745777302773549864511806477792123846746926138422e-18, -1.21885265855885796336587642745340332044954381573101770337247054640773923844104738024035263408343862050173385526271054527779167534527150945599237239085549415e-12, -1.21425621748065225408575213490645023781218746307784563595461167453746485254381894765452671973470031441839940321150801062510400203091338987398709343950868398e-13, -5.89839691360573377853724450845213744663078081702825457280947571531801871991448529847430682271723434012101175024827547779803051740017022082303619737625889486e-09, -5.91578409640887952249942125453315879090063566017586889007453477842274884626800270762589216372517041572015986850551197174831307248982087261410192464796972733e-10, -8.91398307212101009607801428389858240169742361010925716638366337381842937354154872758232823701570455514104726899957850301673701174747592713606872250380322375e-03, -8.42053887872033266653607129436120332986605509406806473085394716808709140464818403678410897844857757662660383585201116974447906995800778540794356121286162466e-04, -2.39454426189012720153949125458607560136428439328896325863340019227971004909464342991364515180426154538135015955086863484223863158207429685619666305145154359e+01, -3.76476518592436858007314935943947387099786881078802995463396589470357101760881597924214768509492139210255683732882889413720830392310400758516232208031214246, -1.15611002005138801589955750209585309425656785647959762466833897140530175776406789969254912953685126670617511886993669968044152633136439031781367528338820182e+05, -1.27924079748914269202104533028746312568829063639140143980976169090762061884244438928270133478423661047746511253816521478052316897409139194708697370604737564e+04, 2.17860680202940154736677306989956812315763617452307317693106308241859078024554915623117220663895877283518663201014746237201880281605674281674771146441859738e+07, -1.35295211902045047462234560566910973781395374029294750252935287589636971847599602997580883503420960231403791872692298957738478446690706323802580237251582362e+07, -6.52254168478287561353183854270634684698245693215925269578723094995717014788025648867983095893236158160343934051854933460507576562553465259801189595513085008e+08, -1.60270171996669494564242144136052294547941513842736400270650412113804906822352822882055714412282718470017834845018642709646006327861946501253577495857201428e+08, -1.05510479827942405702573632590594739953635465625213541460358892880559389573335860223919250790939168673647425045555282042486378234167146876253571648631107229e-05, -1.04533748389581826246886411726826264511227235807991792429322736905816479806819649608164529964927543001553154369372338493111984499721214457849304746258939563e-06, -1.05002972192000229439702291849316020285672890739068639546761034310672966877061789042658389353484800935645621195735739047623637105562132116606914864751660068, -1.15149675771114515803021096162407330795781129899587095252818869757350808028241083614653954193278825311315805426626353818715510122026931255095194981434387893e-01, -4.44381228100737112693182090253007379459030825093465107921125999213354161974548068731956762015242107389876858945586007926865096380025483892877396761258855156e+06, -5.01742138034632934269224907500882694693313640460534352550328347166583232577262299086386333980628156392642149369152384528703881246399355599808733186283913849e+05, 7.79224918689472199195861081037944479237665092662956929348755209232153430880995673247048534631710767123715846804242592082391329730254027074554753693775516594e+06, -1.62146115976380783239541432041346247138569179230755173969867772437263840926081738348758220323002286865772764209527558571773395195611757225779031658505111885e+07, -3.33427211126359983193089904628990529979917324047614292154034207206148441986305412857991643965922299561713908954841027134263899167869822620647118157931227308e+07, -2.31541169432957348033399079412551383543871967833357672502539480250135326918009354653853130749420559462340814963457499669601715483321060326224803208138826865e+07, -1.21272335083649283486540604303043415587014905308303248913343375473852507969078694799956602143177981910881018587014873557764795500591163007205195782504616651e+03, -1.67132476409320837351616030819075542406661312158572529064819045917235371790720935908617573337139894475873138409139873836618460029339202306997350257277063694e+02, -4.74277542875098770854104829468723735135695845093450603965935223581940270892422654513798851051239917982822402146448359348088333366235095395370939462505489894e+07, -6.68341628270893576837713582513503387576170177016307172190623061514220886461206702886096161043251984995989734336037001543754437428404039151595753974789434174e+06, -8.17731934632000632839016573554226493542376244136282909757797592478381798590677210946107610089036904534145667752297833091757689949135816124720486566261689765e+07, -4.86684127008968291933400675516610673071664264036778536766279453364168155601936390557076075215201184595024628273444006984370511982698408874032384138315313784e+07, -1.01694047071340462595719999926874891010990580615098475133244398856441243361902869666221087886874175498478268884401400078434170113309251039034825363797486581e+07, -1.3137013161240231541940424962985937813491161298749289860360988843444699386475352336848242124757539874734228794071092966915826523257001114309763125879336561e+07, 1.59989917421130634682720308841121876472172077576254176831947210372066541560527270967897063979596619627183939102563521782915828850296443235129355530483255114e+09, -5.47662785450991981512398155250562104815255871198950541153369101576605839647990178866004666722264179535996482728128747000990053037517707946548339977416771278e-110, -1.01694047071340462595719999926874891010990580615098475133244398856441243361902869666221087886874175498478268884401400071476503349773218680388036587968660124e+07, 1.31370131612402315419404249629859378134911612987492898603609888434446993864753523368482421247575398747342287940710929664243690696685075324913537282270909861e+07, -8.17731934632000632839016573554226493542376244136282909757797592478381798590677210946107610089036904534145667752297832955700362573524559146579895797728557613e+07, 4.86684127008968291933400675516610673071664264036778536766279453364168155601936390557076075215201184595024628273444006939857242442476529792239610519866950503e+07, -4.74277542875098770854104829468723735135695845093450603965935223581940270892422654513798851051239917982822402146448359337719898889372286132225486049899097685e+07, 6.68341628270893576837713582513503387576170177016307172190623061514220886461206702886096161043251984995989734336037001530032005534324151229974412208408076608e+06, -1.21272335083649283486540604303043415587014905308303248913343375473852507969078694799956602143177981910881018587014873556269537824528584162758456149065073591e+03, 1.67132476409320837351616030819075542406661312158572529064819045917235371790720935908617573337139894475873138409139873834667839881816578858513864470383715329e+02, -3.33427211126359983193089904628990529979917324047614292154034207206148441986305412857991643965922299561713908954841027105465720575142984903880572613671652842e+07, 2.31541169432957348033399079412551383543871967833357672502539480250135326918009354653853130749420559462340814963457499657069399632705966878404125725321566082e+07, 7.79224918689472199195861081037944479237665092662956929348755209232153430880995673247048534631710767123715846804242592082522907775695526743247955119938875843e+06, 1.62146115976380783239541432041346247138569179230755173969867772437263840926081738348758220323002286865772764209527558568001097931274745800201798053205281979e+07, -4.4438122810073711269318209025300737945903082509346510792112599921335416197454806873195676201524210738987685894558600791865697812682232111699408705533592621e+06, 5.01742138034632934269224907500882694693313640460534352550328347166583232577262299086386333980628156392642149369152384519871895211817570663439426974257923207e+05, -1.05002972192000229439702291849316020285672890739068639546761034310672966877061789042658389353484800935645621195735739046774709393028912994880813284237485489, 1.15149675771114515803021096162407330795781129899587095252818869757350808028241083614653954193278825311315805426626353817825320451857684153926903027115116881e-01, -1.05510479827942405702573632590594739953635465625213541460358892880559389573335860223919250790939168673647425045555282041976722227154856622523713591215804495e-05, 1.04533748389581826246886411726826264511227235807991792429322736905816479806819649608164529964927543001553154369372338492629435669099530885542895913721122468e-06, -6.52254168478287561353183854270634684698245693215925269578723094995717014788025648867983095893236158160343934051854933104185561585283027587957614444171480148e+08, 1.60270171996669494564242144136052294547941513842736400270650412113804906822352822882055714412282718470017834845018642665628128259597482631143826997306190412e+08, 2.17860680202940154736677306989956812315763617452307317693106308241859078024554915623117220663895877283518663201014746233123365647952487782987973162373317884e+07, 1.35295211902045047462234560566910973781395374029294750252935287589636971847599602997580883503420960231403791872692298953956833587617306963826787788022748972e+07, -1.15611002005138801589955750209585309425656785647959762466833897140530175776406789969254912953685126670617511886993669966272043759673992949093890811816851861e+05, 1.27924079748914269202104533028746312568829063639140143980976169090762061884244438928270133478423661047746511253816521476178418619849018022104048639800588437e+04, -2.39454426189012720153949125458607560136428439328896325863340019227971004909464342991364515180426154538135015955086863481849738004971876179726390733722305929e+01, 3.76476518592436858007314935943947387099786881078802995463396589470357101760881597924214768509492139210255683732882889410214358583743752585358475308735264581, -8.91398307212101009607801428389858240169742361010925716638366337381842937354154872758232823701570455514104726899957850295900507564849399830715837813296490571e-03, 8.42053887872033266653607129436120332986605509406806473085394716808709140464818403678410897844857757662660383585201116969208737071247404858548862576555463881e-04, -5.89839691360573377853724450845213744663078081702825457280947571531801871991448529847430682271723434012101175024827547777834016523266503625650724800548005441e-09, 5.91578409640887952249942125453315879090063566017586889007453477842274884626800270762589216372517041572015986850551197172959338966554306712792980088428186665e-10, -1.21885265855885796336587642745340332044954381573101770337247054640773923844104738024035263408343862050173385526271054527530330504970231607606259066632418575e-12, 1.2142562174806522540857521349064502378121874630778456359546116745374648525438189476545267197347003144183994032115080106228058417543250449257319359336098944e-13, -3.53840266519784534634346236572959466490796755936423589303096581589894522900429548295704949921034363841097016014084820542829120609333544177800307424868073518e-17, 3.63650949219797153077026801871288631022589877099722369182283745957504622255018333946848480082306165027448314745777302773254514859094434234629475996479234528e-18],[-1.83988087659284115113781398334177994100875269732024934256887737298364003944480994422945130464273915224316543895279348789281574407018176872303211054029417412e-48, -9.38209300305217994349750057966279209375621385908692015949227448106452285194630692850194227580238571119491190948596666585348789797719113495181252533422111619e-50, -1.59546702292430380919359182630177313389683448483574151228103821741973041281571954104866111468662007671726921038455462144989123509078387356331878611664140926e-41, -8.44636285849138582842160274771084423044390073942001684797782703951875625457812847476778860947657610351278620128765011613385724072523483264298900488133933777e-43, -5.8558400189795426025770757235941873147846319002497134435632698465837035817945314447975525930459463302576281297778397866207717503112322803439957223911069262e-36, -3.19872531138664990026898987442298766147160755559364127400095406764148463390520258613602950001630073383860409254391005953916489316392573527843757332457192815e-37, -3.88043093777597215654282652584719304529849587578199558830435974637695424720807815893405221844308384521059430356562138959726292773688229899680183195695579013e-31, -2.18002933387839296782876396811618918274496127158163922592650390705506175607814675223035502797010868402948739568380498822730826774011553994447262922693382827e-32, -8.21231130793020866763577281586214443970819033351939110458786510661891601809712854799079411400682798781320534467909463866341659870438980126762070013075691339e-27, -4.7346317978935639687885830207669642752578943087233433909043558340224152889295776994324209315069245890670785751345472235489687941043755605502635091872155754e-28, -7.49683668488749110120950432546217811681671877755704930266072421602004851570119398965701645332220790360476388039021834805868333355358103857916507445621079894e-23, -4.42785395087220426733843624985961643298884103811137953032892428418493981995443378669867009368563054351651738185898549527637231302222528159291136709598233617e-24, -3.54905308669878220488798837310315133854938140001555832253356228955194692801817861373671522636088608668782628116697440454842509992587688447928737672217591459e-19, -2.14428402036509001721777898751164436337232512248844279729663958830747119702544648580366256429192642652314012609964523837216266274008787574341564685632023246e-20, -9.86546826975794694088531534228951263208321993571576191273572404421652783179105909142646712113602443329150328754951413525009562195305234843663700165583893641e-16, -6.08898655422118469298853899469104862470633410204808475881217686403191612713304568523600968314715945999277280831555518294014241908408295567270045373314539776e-17, -1.76141977037116581975638595569619477768041592064787964059166548504340689985686346515055678670329682291470639783048785636265065005401094106890553057658780689e-12, -1.10904806884551735304586265063034272975039442546644387944779908947803960388275703885977989967852070584418331859995458160622266037345295017747409260191069029e-13, -2.16305396069184180615125476997632368066707790988219199275134922873048695422377018535167047969234588499374812386936456492171746468671476164062845779743607638e-09, -1.38733271576771538209595383274770104467807706642329174443082998588672885735822527508954711781272685896257549768634757043131087024597307077075752207346452329e-10, -1.92970237066782002741164990620223820929814120711630669944437804573816388479168259612673563760845210618843027243503680190297429328194437378870723926112363513e-06, -1.25869289135547243418454609637818971839490694721239791211884188341389572083382136595259452584820969691351275825426933614478326796945115235654646491048909874e-07, -1.30918218575033921200975529295281409811954161040105724196196679705427400443415415343947130567533819553198988986868279482105197210413801877087697353480525107e-03, -8.66792798898576983299948452553663469005613081920659524326532856965751582939646255381690168082917366008580597537901634537473996775197770455812344562846563244e-05, -7.03090136214570914186305569537802896800781375934950019590528536427918821079393119832391380836781520459827770709474514771710784513561452837227883249895083949e-01, -4.71410552929597604807086928146861963623858153207690273134462728061022021249160494568707259531100381015330557974621268580436933728729410961752042153299597966e-02, -3.10182767971058291989905601847550847237470941332084246310673705396745519781561286169441969911517341529252262906937632136484307533210199035848339643401444417e+02, -2.09987562214189569187478817177297117191177449189343728117844674922362321222461221243113741272297340419276440404840082793790503167826573388954620030682273701e+01, -1.16589678475657136465007869246242314260811783122865744945790773888534905251928352303730242541952003211945569668678349003748130302727387720244664436424182376e+05, -7.93817391377214073630263961473344697154657313403045113068087766571132325272166306693073023179323831544152423063918082194803859673217988149202300743747059213e+03, -3.88112835142506772650456120961210499895736988156591978954036251650197602785461015065631833500252570126566465519533916244480582510312149583434825903556345966e+07, -2.64320784160629092311981618023400741862710860587864982142037015366808287327180282084694292884218988431302496827619925875003839171561398336411832266340117977e+06, -1.19688732683999656480990736113374372390883374829318836169540367086695236639569215384309150076998531027666583662087119483586993762026368677689972265505985791e+10, -8.08760417232907481027893511739992149349183382852182091845077134115579203573126887950474743424110741288780120885908906951696827316091094788635011092694891617e+08, -1.16294481698254009628908537964229852530247346982879723133124344475318130806019876352804040206145911167419242242978205631628573945319915654837861266355532327e+15, -7.36094718917465671213173709911297979779120251523679429647557344370040517623455905905305230760480173972449636740289025119562617179854620719460823283065026022e+13, -4.19426284286931401574591526303618330404951422217454610110700814444644523905304369207947495427982903863421043125772651105130120638027239857872101469926009466e+17, -2.43245117351647323618292518601842505146512993404552987181708567218691187400395118585144031090022132680143114345673874629377138905258164090164537421468979928e+16, -1.02231998237724192266788221555247182307497185430973964978372258346261572287646899234483338689875322453408609483384343536038313039483622195179132949519784731e+21, -9.99081986239923712704043513459499349967066099128455015292236715746259625460784946018369879223133644568508502652847659924773625260844624964481442593358975106e+19, -2.51718984041460991992495510464960758858900573271396753040985983131232574111752042882610021527544171321230772406582232789614463022892835479626235708132808878e+22, -2.38693289149594494976050438930554589547798526738009862997398470928618624151769691853035145087834274212487852335185147222288210431160546918353732423885791662e+21, -3.34431236705954891716981568927686387249949902898271108445670963421276850830799143989337931987845131598591254117508395406108094136467286826510627990318580038e+26, -1.887329423303494164213422078265434799855121420739978448841723156804315870707179897919142142481659065658261900008257703543660351041370636404843042024972684e+25, -4.97802202312267943606884278836429516061689034420109466785805210076758909120655537230261692339796348607807910492514067463046809018184205124196781003805650015e+27, -4.26144882672320889536903091704396944321996930645286247899670766392067048523310432662577380001699475566209831337618210395497797309854902683586412946841424411e+26, -2.50184375254691581731564036873072226395626085807405648727075936515337780846855678407112923841443467851303636430509822956390009739940079193858197169966472503e+29, -2.74824169231228789193420024884436116578125942155713040114033469628697856764148534341930191934456204426713373807505152023552377425240939941191971410290321428e+28, -3.47698680899513098719994549995519721012442201410436524882984746477938014519219899842718538062082300930870517833134577238540317651096846647170313020836458694e+33, -1.68454882954879948106206921205339608593765175974874412577489923496517144796536576039173230929130999034056229497223448930724457402931611469099742348756628099e+32, 1.12718481394216732542670561520664033734984723126578826415505710589373128636917825589776235980269480320467765181029015503816892986019703833585809841551884166e+34, -6.48108166301072903432622763362015198309981620567282530507064038322263086502911004944601350421255107229286113215228917497086608381373532887857902104085214477e+33, -7.05975363737320394312952285506714208442623609721910586655361309641411706917631279559321524097301738471286960998661787528089882151775218928082773198470660126e+35, -1.09563075525896856865337804489737035262585834508317404239199715209828457511237994286807882533357927199530028554362858947112755618231808840326469951677682164e+35, -1.51000385935072637610876971936864733646723714494156098994682478135665598468217465141862663818378376380540275631887335662518015374022327130735798174199683246e+38, -1.25711722370408912375618001790517051424849494220216720130084057184860836257838736788301541052184615999751512956102686819026019087821796951405849458718763205e+37, 4.46884481381938252464575893419811094264160294055432760876832993636354184532607737283184867548676815892053234431477909449904900421405405522994309114317362997e+39, -4.65937775260822112061210789900916049545163576034473858089403945042242263393805388275760939596766389816482627200925280247912804313084144460715814324781470993e+38, -5.75140108091813185510522670792658580857921202078093559475698775552101434448012505911262929008410544264622068042929238364097590848678445091782473989422467839e+42, -2.05797907991303018493695029466195771967746696662743960215608954748666402299203441219856678945206492883548802134592804432691849792900529019191998154002610624e+41, -1.24419647031780912793999468362506755854245179486796030747264250402736254003544074159234806665354947252291997618966666407980848866117803701763572831499196677e+42, -1.21020462159889270023696201725162769191590868659598324325370546280312782682374897094812481046710197566732278049175115142695321731857209947265114061320507998e+41, 1.25953408137379189531451723712573237827837466653646250998481664641187834722068801726561586713058030191975120863192782635082264701584888617052585333501543692e+42, -2.54911743091415544860696765476303317850795436856906617953996532870224475702378926425855536666265808333025591501925700205807719851178905607444266895304462422e+41, -2.52505413489774295177412165353402870892498960632373261727604111186211528476268506299770918399337940810828855338956875188910596851848922738610639211344377842e+42, -4.49560407696293799826867619950976244627608057514537878892092167652665098581475679138424299269601443995426483917869111763989536323911520517912021514129496783e+41, 1.73674857284893872993061774804669471038790632063228326576157458010252529531294406499799873500784386219621146350436213818075100706855270603346911986587301132e+42, -4.17537170233987875533827740982636293492697411936682527130125994452260027338434605031343692518558907382476975398533921297782884352827569259864547064764661231e+41, -3.6221476500673136726946751547544362901355657906256749184906650546684720249682951910531407876133031514966022480280968711696367390924231545306086868687687241e+12, -2.39686106859116230398365549946588200295037406719977036595828480729632059365938529824871090129746905856537423509951444285082569521944517257677037458257603259e+11, -7.55048060971562460212286849078765362027222234243546061819609320687153500522139816275530466717473561151572707213443161317517257947592271374889168194641256377e+19, -4.26651834774783537244708141333014250302381418235482032116996242828652266628676602006223149133977355510200124477589614201083053934193866970962627950706245557e+18, -1.837107023658039342123244104218039482057870388351076174068391851202549544170245090693246453937331045056425107843372772143106000260354287733439877725891639e+24, -1.38500029781821500269099960990575316238813551950658970658055168348844831120970687381164928702048618132872578855419147082158534345543238209075841112855300883e+23, -1.29398807924293304600526132796718633467665275864920995926493830231320307971578167712645039665826794513922872771412082296956134546413872633095357000491306068e+31, -1.04135685661959432772295108521673709954486930433070734107307799683057335430765322911092987150200929033632322818338124262838547856214938424744222359671694856e+30, -1.22182185016544854052150273693708478505085344039233191260361007831782470573596003873329301109661144017921615279220840599380291641121686867614153867773444334e+35, -1.87749199320609174824754945582663002971025909919110299335028207133260776103341310000464848480444092868587791559107328897042117347494647283957759169760064111e+34, -5.12992926924623733649731490581955083598297267776787944966828926782326058036544945740805998117405467165659196151769211399678024036972225233831448166406276517e+39, -2.90200282825545360891543587187730313427627944445687439637022630987507842937288768382588529078355230159573280975473758039058393964590152090043993471530639649e+38, -5.33908954469699581590582243637681100463638117345194171516409213442768083040107055817765814891737875264872912105636131095387086707345502994789259972624042163e+40, -2.09248589326238362966753090270358969516879922473103093456439328228544578942452211375824718812744544924525416842069182381262107950861840366934761937671049748e+40, 5.68294291227075298021320969302221372876941273082519147779751243482741947632385569544233802396461321022649236178317141897750860841181002987118448361221884049e+41, -1.7192046285171834494624578588907606090005601449807411641179572737787802663836058920678054090036123158718182356850402459320136614780479232613981070799919647e+41, -1.06434207184359461451542125562819880956139265409347568921351569500405116458646272733034423950409446818382425894722964520131621693832839892374607194661273332e+28, -2.44459595621214589876605132720257750795510061386382782872879555140763469152557266601628397194571482002835645916389707161280355395222379210357202252586847921e+27, -3.31179149183154317445964443275610859428364395502596766115828568418500497256062652362234201880995576830128179834627625787289365020534949993528067438407928608e+34, -2.721676394167039848454121837329431634028641877254123439670427276946848599945299309786373221299552244810020324346099513203125525532549110471898970029641978e+33, -1.59402526627199462159905799447196464422340457549126151543556758469884520556192847736336264831957969170288164495741980705531214872210821942329482388110393284e+39, -4.16291854658848806963584244952582277405133886026219100462447573391430226749286049688177739537609483979652851926432511370890913855842852564850939519550303411e+38, 5.82106674106204486273651730981465631848070713951207644174631261806115841184677443560064301477624154408616670305391368457839793725440350233390639879895979987e+42, -1.92307855421051048793792752917692283442179067841290480333986428222717550014388693421971313144104902090037897704070143760813144566889590962103091353824246828e+41, -3.0039764239584550911389335875314184085689008614673388076898521481519207491577305149438915811931726698207326047993354097200539310369545823717034791606202949e+41, -1.85380282607734216528006249297890482087750220526007876152172404922801339681517016213951728632745169847101525962194047471388077845922160620797867494872425769e+41, -5.35857581366062633945499578048880677140283295723779521740875687426074975843803723625797920589097145523724204029129453883358893162873736663341774989770034492e+36, -7.53716370444984072203632828122772808908063219972438370783359704756650476601677319317862881185787510573486960467208761802820136002508269577306568538040178749e+35, -1.17147403929900278069154814178241521863992457612589259553183815869339615741198965290546498894831191932019879438737466077482064717977057142086477518111410748e+41, -7.72473516982373850942261870134193087818890103946369081245514975988659972632158575365467066413760261389285682346376475243208772338536296528082834262146595404e+39, 6.84535794015595735762159577268443571051002733513861584289250925068702165137283690110556084124899129945208824103620981817010335858487719318245043038587087242e+41, -6.87440161729820569633970554257186895914451902310243984715200705503693347872148752867780963261186111355368087694425270073060224025891173497628813927219436922e+41, -4.47888335053776869572158371819320863731998351844001759938591455004961706301489870835798382476857105563179778905509143070593508598716858480445175560052119294e+41, -3.30521636482619930692353687320800159249409968861276937699601629555453031001665350385354809671197665208679524741423809922506413152118565056318231503835874841e+41, 7.43417609219971950650106430547779821485267786742260856320816766022072279519307738307180334255443035622167770733496259693836595218583540400034285527387677871e+41, -2.23653971192495859415168959188498719529209818714961951051727662189056283993720098324599128187903905659706380796665076857915692707181229403711635536043705603e+05, -4.47888335053776869572158371819320863508910414040878327864260852453196030848010327347054108326866381720085654495646268157305855863507557467397441035549027134e+41, 3.3052163648261993069235368732080015913305195249576424181260284804944639449209689640526886374101810028783281011331617050430337540505214862072454042683906278e+41, 6.84535794015595735762159577268443571245122437021503116100813929799402425646516161812417186162248032398304305260656533782458002704210322224067109796905773631e+41, 6.87440161729820569633970554257186895354947010859974706504013072791721550720503846490690427466576779395752126279123192122258375149276102438210142944423740535e+41, -1.17147403929900278069154814178241521837917312138949518903546045598066291124079811835884098499911102031104778434503448173001200658198169569436992661881477366e+41, 7.7247351698237385094226187013419308765056176381518827804841337814852975384615010692857136848982526421976173002508988138307485845663861656867169399686487044e+39, -5.35857581366062633945499578048880677054963242562768042985441535764476069465994742607172722356343956912852952056085263416622401468750103204760331546711867943e+36, 7.53716370444984072203632828122772808791437446364046664409915141437955381721221329806379221501018187875503751862784905746106120032749595982653163048583273316e+35, -3.00397642395845509113893358753141840635816389685284678443766298105368051887634920914601575223628097192017135922525546741514050054895420268289193016994075849e+41, 1.85380282607734216528006249297890481996482184609215866427705129302858276654412037686414860190596230867446199603458923833966556378712432753089321683151646689e+41, 5.82106674106204486273651730981465631710787720157551760807023050062215554352813233034886855191069397249961348052435247620855825951391256442531641808382555496e+42, 1.92307855421051048793792752917692283396274888521928999887262228293910129620681505526587882389299967037406818825662786746056410084621230668986631894355220592e+41, -1.59402526627199462159905799447196464388730807985979061446214523114446093066640815079471042238680382329155835522082131968449838067648613968970880273346662897e+39, 4.16291854658848806963584244952582277323448914029757618217564564793603530845939930728073165678288762202319669089255597638495705770074478920539554712177461867e+38, -3.31179149183154317445964443275610859384979195738430134924868869684507532034709090681413346725841947600079935684420323538412935221140239810074404976352202468e+34, 2.72167639416703984845412183732943163367657795598609134353142750469069194593733414501160588071296539830912787871623343187518471800594541247577480973026599473e+33, -1.06434207184359461451542125562819880944062557227707993909926000074485488764847105984438581346126096834639369489645118119480176055691242616860974223967211806e+28, 2.44459595621214589876605132720257750768485579606654606768499746777182167420009126514580754612967898141078860117602000657444047110427676612192255956099367363e+27, 5.68294291227075298021320969302221373171320357618933253445766563610511583137014540888541097821045743914825502922409716053263513752126115820163550301108947938e+41, 1.71920462851718344946245785889076060484493495999839548198620829058144500352737873670374254471220686947494486551563134534778947419928901735628397257653645334e+41, -5.33908954469699581590582243637681100291934303312310493261281174173809483967539477481843313128008697440405566737075593235333542413137477982236738327456214835e+40, 2.09248589326238362966753090270358969459260713128266714024024372307807638350408043387435451641086257138207703476208759823993065276254471041668416081458667949e+40, -5.12992926924623733649731490581955083507220251471942858672656065633239960998818496898086521282924927411549645078970549494162436374734974026638121106782700755e+39, 2.90200282825545360891543587187730313376811825088730909828222295792030205010683239914774079216078955270395696628777886342681743674588290555635660823121724182e+38, -1.22182185016544854052150273693708478487603081731288737599663600449550300145408082143617432517763693033648647159873910875434489141728413541718907438572953712e+35, 1.87749199320609174824754945582663002944867028409869837904282934201733423350049867468150770584959498720964730128422011524115644058211993464152793822851446775e+34, -1.29398807924293304600526132796718633451952320128339873020551143090998302324669384859264066451544603203212618276496180642824787824689860620867670418802247373e+31, 1.04135685661959432772295108521673709941978098761952939466142118031224785373184197159942523989496376949368021263166143462199247234585337664087818803632209347e+30, -1.83710702365803934212324410421803948186901100769187667144143892557383180767851327895496971390889888238411379197185468968564705618440182737663951554110024604e+24, 1.38500029781821500269099960990575316224678072203542218668112369736574491675204582216580409490029851913676608576628936075614967734602310913098079543534872693e+23, -7.55048060971562460212286849078765361955434557425671648936114950700024374295999935254012896840544517161910957106760902497381107037979934374133805690622354273e+19, 4.26651834774783537244708141333014250261999118094864423859228013267594601023302037700984722600562685528752637583486407005714704369238210702177416247599565366e+18, -3.62214765006731367269467515475443628981604562495156155525473136854755349335580524400892934183259852706214532113546407246274269836403176134363517162352529428e+12, 2.39686106859116230398365549946588200273984570661271719317414053240409924065376263369987875594799195553763664619902755898112467225776510284622583452318246221e+11, 1.73674857284893872993061774804669470930344438717347578445004275490688423078079657730011231153662382602630979416418213806361471299068660891902944024019714328e+42, 4.17537170233987875533827740982636293007645910447609791374051550089624481607308858127509083421602456177788927441051079028120599988915258711008597504003041393e+41, -2.52505413489774295177412165353402870700714279693199113112963375339040318321983672031954749263687369272572091084261633145961924583333105473927881157053366121e+42, 4.49560407696293799826867619950976244339964813901803838606989605931733027866678786358774744381318826659287613611782662004448590204291535992375819169765621644e+41, 1.25953408137379189531451723712573237784386064594848696894053907153226292283380427071833306097251502205152723794895152136512640063032593914898591078329075023e+42, 2.54911743091415544860696765476303317749818628115700254381046632628783153721468996733967821229718976164874637532844021169224327729618181760203078506854652322e+41, -1.24419647031780912793999468362506755812602383722339863279985878989041132110310973332397026999591201821002840055111995187104166109492097293573900841254710792e+42, 1.21020462159889270023696201725162769152982022797944092240700207692745698707794621354145544569201848203656290547300189980847695730532884055361294311054966683e+41, -5.75140108091813185510522670792658580722010479532301805023348229304596227295290806288437273810276121557755409312380420996802084458011804137367295705380039924e+42, 2.0579790799130301849369502946619577191972221722044699499780537521142824906559777314646175187195235664080865923939952925456427193274802084421876053834932632e+41, 4.46884481381938252464575893419811094185772075719676783311673652872872275275797167959273679197313050666397140642599277724202696552762891596400070759157679081e+39, 4.65937775260822112061210789900916049461197618573977764501159384927031410760037138086781215838077022346323523036000524950746446343247688941240554659028220906e+38, -1.51000385935072637610876971936864733621290112036277627493163925801501477666954365890803299859574738558099293973955928965371043287356736502743377462898830381e+38, 1.25711722370408912375618001790517051404067806347723651244804237496466240125385991195317503526922295445547618874868879653266148607735550660657286251002331726e+37, -7.05975363737320394312952285506714208336246036493815442473621603338515119602243861174229609184828206408475657589166217514348661051019515174657155183631731437e+35, 1.09563075525896856865337804489737035246548518443057638864046970563768728153647507478075279419592540244555575082847185753775540883680842502918535425750420161e+35, 1.12718481394216732542670561520664033721429960769349328042258341965807296479096528734063263036571877757832734103094408550222049869740299592863605826206667405e+34, 6.48108166301072903432622763362015198224064281959849851485095556440244212321292128835443456932891939771039885115937459873354703793818536263792750595196310609e+33, -3.47698680899513098719994549995519720968347516325047160075141463438809432722352272542825075713833961115212742026771367516848282742646761871193518609934798409e+33, 1.68454882954879948106206921205339608572553767978622189133279256516851658294887015534804946896802968347002815000029789881773194168351141672513222913334118459e+32, -2.50184375254691581731564036873072226366474725270898411125645455763283655648746934579072290159245662286229113438627877022038974903593954956697956902124869369e+29, 2.74824169231228789193420024884436116546535448636156538800679452980617938754623499534218981785954978813957272001098027478321648102850160120084837495504576425e+28, -4.97802202312267943606884278836429516007432355719743992935880181517740254887176726692796660974798178327028625810786469976794264179896620410990710595467910766e+27, 4.26144882672320889536903091704396944275981133873171546579582575319921262595115645369100525992192403043747475915306034572121350930188888190041323845960015712e+26, -3.34431236705954891716981568927686387214460410579333131242949766320578657842253690052736063762975003983144788113827217859485808006822710613916322838056368946e+26, 1.88732942330349416421342207826543479965600776610235167484545146535315059693211785595067434217527151539297365219583734963798122169436652099359903088009114072e+25, -2.5171898404146099199249551046496075883379337865968750403473530887825606110832867031625288512435005652561429559009234260559088105654196291454383178945688311e+22, 2.38693289149594494976050438930554589524190640346695715869393576460237536497599148096834188078835293814988695975441080141903252403466765230011380776129736408e+21, -1.0223199823772419226678822155524718229755899757681333177407473996966481538809217173476837654427309620663754502426556348867203687544447162342218360833376019e+21, 9.99081986239923712704043513459499349870732938109305084127216063387421108875213009047230086357374415362829980394828722463149334778883523674845147491253648054e+19, -4.19426284286931401574591526303618330366012172911381445002945218561937241545346506331168699501850912012888182162889494301186740417289213742394966414475311694e+17, 2.4324511735164732361829251860184250512402818280711871513960747667986281102528285419027479397234551633412467426280125823437713627677682306793801913162740502e+16, -1.16294481698254009628908537964229852519725821449317044056607335731451993340493851264282800475286229025629407731274682644140905829470354116732454488300922192e+15, 7.36094718917465671213173709911297979712816762119695977675215601145204386024448906682855142566401367112975904896780149210846664874407209169320022719790247263e+13, -1.19688732683999656480990736113374372380577787251807927553869608216511415808362467399797438096038097607283436744006406632417573858862933405304691935909995853e+10, 8.08760417232907481027893511739992149279830202647516321516748868641753226530549027365098557138512980058047249732197929315055395444832440080791760246915917091e+08, -3.88112835142506772650456120961210499863080206587136169666983029567715318279465993980138491503824385738791455980441573953920111444596050743292504360095894161e+07, 2.64320784160629092311981618023400741840555444416876665921684897900368568387308670046100593985335364053825709547126968476707077063903965071206010970478092599e+06, -1.16589678475657136465007869246242314251214289573883563934574789756919248525383625269057332518956767311381794612864943819172855555239685271576533780543714117e+05, 7.93817391377214073630263961473344697089545283651074103139736916474336737124912550128990630890582673140759250483272974853662517975374224810864009113654062474e+03, -3.10182767971058291989905601847550847212464909088997730693181501147203803919138448369905650403440151289370098157482281498427685741078761298797424985299127821e+02, 2.09987562214189569187478817177297117174305273426690391631344864317623671847777094510882988608134829394432977653418766924257951034266520114321601298023633572e+01, -7.03090136214570914186305569537802896745220470877296549773563492835806949522505090174480713140891132330761121384431559921767255922360026642876325277881281614e-01, 4.71410552929597604807086928146861963586720839231950260404736494678775228050961954792920551720565760548735875480651080889654806646791449584537406362042361066e-02, -1.30918218575033921200975529295281409801804671340748802029022169341309484137835019596185238651796555763498051112185210293299486103656938313265354306999463921e-03, 8.66792798898576983299948452553663468938607898050577306027761894318024753244654299544333330483039001906940809458283902890535082626713290136652082576051588053e-05, -1.92970237066782002741164990620223820915127324337586878587578852737907502498610153958107438664986229668290308410397190603557928360798945405634025365040362397e-06, 1.25869289135547243418454609637818971829936486468448605393936620342451105711367148188425509983429282807912154911586009074467545223811869746698243133166594006e-07, -2.16305396069184180615125476997632368050536111324127480767604244983822339107818214920132061966933990640852226376477856855867860532098715915087644879025350314e-09, 1.38733271576771538209595383274770104457461317619545007241209069027384912923049587409816318874647231200999997671779646779810012855428289528762986033475836271e-10, -1.76141977037116581975638595569619477755099322084856479415686579153823377416467071311460759356773916285667292127835779583147151982336038989469599610352839709e-12, 1.10904806884551735304586265063034272966909381109400836080484438366870288665466514222447009639003895750835936322385540643635100788658244866884244121920927557e-13, -9.86546826975794694088531534228951263137056104152511544645979121708086105601912122422791235211576111143772032063013933692303425749219888572942833148781939112e-16, 6.08898655422118469298853899469104862426742559157933586490177671761417560023400544962633141851841701525553067734885212536019001492878371808646037683151230000e-17, -3.54905308669878220488798837310315133829726993067973285650272762730952152659186515238333783901623478488143273851183328588016087824168169729060751242487626636e-19, 2.14428402036509001721777898751164436322030865053801230809196346602655263543849599366187785077482655334714267009740403546085648440246817779845206341336138281e-20, -7.49683668488749110120950432546217811629298740970472247992013551393142771426499625802362082209243113658896043108748805082043700964525308758658912120267963685e-23, 4.42785395087220426733843624985961643268008887596939910731718482405880688137912880372660651576794209951368598676672084573770506862984844855473434344206782803e-24, -8.21231130793020866763577281586214443914403289774771722154143336195292900079782699029604763260015842327585099475031950805747126110835435139548005506501622752e-27, 4.73463179789356396878858302076696427493321053711604683152824418167355189199806996041776652929024582060192306709494700612231930949740789917740715278495972229e-28, -3.88043093777597215654282652584719304503645747535748203969076687198970525554096973998490068789988765896702036024602059465267010435894654886147192663598893811e-31, 2.18002933387839296782876396811618918259798877443647196899593583025907448041230636410217204851242960981813974188206918006176903350753033766806136768668972741e-32, -5.85584001897954260257707572359418731439620888430168526681428856809827140644300139843871690779667868652850378543553931620772793145636117624553239715995888533e-36, 3.19872531138664990026898987442298766125975797012200652934564984576533817910038474169497192705895911580455957546005431124801690408128398267992605571314771076e-37, -1.59546702292430380919359182630177313379303063545451673255880316144071865708734117588492607484017726697084160449960047850617848197781622821251865605022468011e-41, 8.44636285849138582842160274771084422989515072100993445600761727334070552921772000417449768404284652234543625077299867199392945724970599319409676391657968468e-43, -1.83988087659284115113781398334177994089171123500271191809602147357147879377973850970932232790714243556414288862177826123749327857095650830640101665856079829e-48, 9.38209300305217994349750057966279209316017584821723596075410796346480482352267109964252286448564627542179255284701431937543703424141620039139565738218154791e-50]
)

#using Base.Cartesian, Reduce
#Reduce.Rational(false)

@generated function max_degree_poly(::Val{N}, l::Int, T = Int) where N
    quote
        j_0 = l
        s_0 = 0
        out = Vector{NTuple{N,T}}(0)
        @nloops $N i p -> begin
            0:j_{$N-p}
        end p -> begin
            s_{$N-p+1} = s_{$N-p} + i_p
            j_{$N-p+1} = l - s_{$N-p+1}
        end begin
            push!(out, (@ntuple $N j -> T(i_{j})) )
        end
        out
    end
end
function tupGridd(x::NTuple{N,T}) where {N,T<:Integer}
    Expr(:call, :*, ntuple(i -> gen_diff(x[i], i), Val{N}())... )
end
function tupGridd(x::NTuple{N,T}, j::Integer) where {N,T<:Integer}
    Expr(:call, :*, ntuple(i -> gen_diff(x[i], i, j), Val{N}())... )
end
function tupGriddD(x::NTuple{N,T}, j::Integer) where {N,T<:Integer}
    Expr(:call, :*, ntuple(i -> gen_diffD(x[i], i, j), Val{N}())... )
end
gen_diff(v, i) = v > 0 ? :( $(Symbol('`' + i, :_, v)) - $(Symbol('`' + i, :_, v-1)) ) : Symbol('`' + i, :_, v)
function gen_diff(v, i, j)
    letter = '`' + i
    if i == j
        out = :( $(Symbol(:d, letter, :_, v)) - $(Symbol(letter, :_, v)) )
    elseif v > 0
        out = :( $(Symbol(letter, :_, v)) - $(Symbol(letter, :_, v-1)) )
    else
        out = Symbol(letter, :_, v)
    end
    out
end

function gen_diffD(v, i, j)
    letter = '`' + i
    if i == j
        out = Symbol(:d, letter, :_, v)
    elseif v > 0
        out = :( $(Symbol(letter, :_, v)) - $(Symbol(letter, :_, v-1)) )
    else
        out = Symbol(letter, :_, v)
    end
    out
end

function process_weights_no_deriv(x::Vector{NTuple{N,Int}}) where N
    if length(x) == 1
        return tupGridd(x[1])
    end
    expr = Expr(:call, :+, tupGridd(x[1]), tupGridd(x[2]) )
    for i in 3:length(x)
        push!(expr.args, tupGridd(x[i]) )
    end
    expr
end

function process_weights(x::Vector{NTuple{N,Int}}) where N
    expr = Expr(:call, :+, tupGridd(x[1]), tupGridd(x[1], 1) )
    for j in 2:N
        push!(expr.args, tupGridd(x[1], j) )
    end
    for i in 2:length(x)
        push!(expr.args, tupGridd(x[i]) )
        for j in 1:N
            push!(expr.args, tupGridd(x[i], j) )
        end
    end
    expr
end

function process_weights(x::Vector{NTuple{N,Int}}, deriv::Int) where N
    if length(x) == 1
        return tupGriddD(x[1], deriv)
    end
    expr = Expr(:call, :+, tupGriddD(x[1], deriv), tupGriddD(x[2], deriv) )
    for j in 3:length(x)
        push!(expr.args, tupGriddD(x[j], deriv) )
    end
    expr
end

#p1 = max_degree_poly(Val(2), 2)
#s1 = process_weights(p1)
#rcall(s1, :expand)

function weights(::Val{N}, l::Int) where N
    p1 = max_degree_poly(Val{N}(), l)
    s1 = process_weights(p1)
    rcall(s1, :expand)::Expr
end
function weights(::Val{N}, l::Int, deriv::Int) where N
    p1 = max_degree_poly(Val{N}(), l)
    s1 = process_weights(p1, deriv)
    rcall(s1, :expand)::Expr
end
@generated weights(::Val{N}, ::Val{l}) where {N,l} = weights(Val{N}(), l)

@generated function calc_weights(::Val{L}, l::I, m::NTuple{N,I}, mcourse::NTuple{N,I}) where {L,N,I<:Integer}
    quote
        @nif $L i -> i == l i -> begin
            weight = calc_weights(Val{i}(), m, mcourse)
        end
        weight
    end
end

function inds(i::I, j::I, m::NTuple{N,I}, mcourse::NTuple{N,I}) where {N,I<:Integer}
    distbase = mcourse[i]
    distcurrent =  j-1 + mcourse[i]
    distcurrent, cld(hermite_weights[distcurrent],2) + m[i] - cld(length(hermite_weights[distbase]),2)
end

@generated function calc_weights(::Val{L}, m::NTuple{N,I}, mcourse::NTuple{N,I}) where {L,N,I<:Integer}
    weight_expr = weights(Val{N}(), L)
    Lp1 = L+1
    quote
        @nexprs $N i -> begin
            @nexprs $Lp1 j -> begin
                i1, i2 = inds(i, j, m, mcourse)
                $(Symbol(     '`' + i, :_, j-1 )) = $hermite_weights[ i1 ][ 2i2-1 ]
                $(Symbol(:d,  '`' + i, :_, j-1 )) = $hermite_weights[ i1 ][ 2i2   ]
            end
        end

        $weight_expr
    end
end

@generated function calc_weights(::Val{L}, m::NTuple{N,I}, mcourse::NTuple{N,I}, deriv::I) where {L,N,I<:Integer}
    weight_expr = weights(Val{N}(), L, deriv)
    Lp1 = L+1
    quote
        @nexprs $N i -> begin
            @nexprs $Lp1 j -> begin
                i1, i2 = inds(i, j, m, mcourse)
                $(Symbol(     '`' + i, :_, j-1 )) = $hermite_weights[ i1 ][ 2i2-1 ]
                $(Symbol(:d,  '`' + i, :_, j-1 )) = $hermite_weights[ i1 ][ 2i2   ]
            end
        end

        $weight_expr
    end
end

@generated weights(::Val{N}, ::Val{l}) where {N,l} = Expr(:quote, :($(weights(Val{N}(), l))), Any)

weights(Val(2),3)

rules126 = readdlm("/home/celrod/Documents/notebooks/hermite_rules/rule_1_2_6_qr_0.csv", ',');
nodes126 = rules126[1,:]
weights126 = rules126[3,:];
using HermiteQuadratureRules
X1 = herm_design(hermite_nodes[1]);


text:
struct Params_SS{ComplexArray,Total,KF}
    # boundary conditions
    periodic::Bool
    # normalization
    total::Total

    # algorithm-specific
    # gradient kernel
    kernelfactor::KF
    # fft buffers
    complex_surface::ComplexArray
end

function Params_SS(img; periodic::Bool=true, kernelfactor=KernelFactors.sobel)
    box = size(img)
    complex_box = periodic ? box : box .* 2

    # scale factor
    total = cnt_total(img, periodic)

    p = Params_SS(
        periodic,
        total,
        kernelfactor,
        similar(img, ComplexF32, complex_box)
    )
    cf_type = periodic ? :periodic_point_point : :central_symmetry
    p, cf_type
end

"""
    correllation_function!(res, img, params::Params_SS)

Compute surface-surface correlation function in positive directions
"""
function correllation_function!(res, img, params::Params_SS)
    ix = CartesianIndices(img)

    f = params.complex_surface .= 0

    v_f = view(f, ix)

    v_f .= gradient_norm(img, params.kernelfactor)

    self_correlation!(f)

    res .= real.(v_f) ./ params.total
end

"""
    surfsurf(image; periodic = false)

Calculate `Fss(x)` (surface-surface) correlation function map
for the N-dimensional image and return a `CFMap` object.

The `image` contains the probability of the voxel being in the correct phase.

# Examples
```jldoctest
julia> surfsurf([1 0; 0 1]; periodic=true).result
2×2 Matrix{Float32}:
 0.125  0.125
 0.125  0.125
```
"""
function surfsurf(image; periodic::Bool=false, kernelfactor=KernelFactors.sobel)
    corr_function_map(image, Params_SS; periodic, kernelfactor)
end

function surfsurf(image, phase::Int; periodic::Bool=false, kernelfactor=KernelFactors.sobel)
    one_phase_img = image .== phase
    corr_function_map(one_phase_img, Params_SS; periodic, kernelfactor)
end

ext: jl


text:
"""
    rect(xmin, ymin, w, h, action)

Create a rectangle with one corner at (`xmin`/`ymin`) with width `w` and height `h` and then
do an action.

See `box()` for more ways to do similar things, such as supplying two opposite corners,
placing by centerpoint and dimensions.
"""
function rect(xmin, ymin, w, h, action::Symbol=:none)
    if action != :path
        newpath()
    end
    Cairo.rectangle(get_current_cr(), xmin, ymin, w, h)
    do_action(action)
end

"""
    rect(cornerpoint, w, h, action;
        vertices=false)

Create a rectangle with one corner at `cornerpoint` with width `w` and height
`h` and do an action.

Use `vertices=true` to return an array of the four corner points: bottom left,
top left, top right, bottom right.
"""
function rect(cornerpoint::Point, w, h, action::Symbol=:none;
        vertices=false)
    if vertices == false && action != :none
        rect(cornerpoint.x, cornerpoint.y, w, h, action)
    end
    return [
        Point(cornerpoint.x,     cornerpoint.y + h),
        Point(cornerpoint.x,     cornerpoint.y),
        Point(cornerpoint.x + w, cornerpoint.y),
        Point(cornerpoint.x + w, cornerpoint.y + h)
    ]
end

"""
    box(cornerpoint1, cornerpoint2, action=:none;
        vertices=false)

Create a box (rectangle) between two points and do an action.

Use `vertices=true` to return an array of the four corner points: bottom left,
top left, top right, bottom right.
"""
function box(corner1::Point, corner2::Point, action::Symbol=:none;
        vertices=false)
    if vertices == false && action != :none
        rect(corner1.x, corner1.y, corner2.x - corner1.x, corner2.y - corner1.y, action)
    end
    return [
        Point(corner1.x, corner1.y),
        Point(corner2.x, corner1.y),
        Point(corner2.x, corner2.y),
        Point(corner1.x, corner2.y)
    ]
end

"""
    box(points::Array, action=:none)

Create a box/rectangle using the first two points of an array of Points to
defined opposite corners.

Use `vertices=true` to return an array of the four corner points: bottom left,
top left, top right, bottom right.
"""
box(bbox::Array, action::Symbol=:none; kwargs...) =
    box(bbox[1], bbox[2], action; kwargs...)

"""
    box(pt::Point, width, height, action=:none; vertices=false)

Create a box/rectangle centered at point `pt` with width and height. Use
`vertices=true` to return an array of the four corner points rather than draw
the box.
"""
function box(pt::Point, width, height, action::Symbol=:none;
        vertices=false)
    if vertices == false && action != :none
        rect(pt.x - width/2, pt.y - height/2, width, height, action)
    end
    return [
        Point(pt.x - width/2, pt.y + height/2),
        Point(pt.x - width/2, pt.y - height/2),
        Point(pt.x + width/2, pt.y - height/2),
        Point(pt.x + width/2, pt.y + height/2)
    ]
end

"""
    box(x, y, width, height, action=:none)

Create a box/rectangle centered at point `x/y` with width and height.
"""
box(x::Real, y::Real, width::Real, height::Real, action::Symbol=:none) =
    rect(x - width/2.0, y - height/2.0, width, height, action)

"""
    box(pt, width, height, cornerradius, action=:none)

Draw a box/rectangle centered at point `pt` with `width` and `height` and
round each corner by `cornerradius`.
"""
function box(centerpoint::Point, width, height, cornerradius, action::Symbol=:stroke)
    gsave()
    translate(centerpoint)
    # go clockwise around box
    p1center = Point(O.x + width/2 - cornerradius, O.y + height/2 - cornerradius) # bottom right
    p1start  = Point(O.x + width/2, O.y + height/2 - cornerradius)
    p1end    = Point(O.x + width/2 - cornerradius, O.y + height/2)

    p2center = Point(O.x - width/2 + cornerradius, O.y + height/2 - cornerradius) # bottom left
    p2start  = Point(O.x - width/2 + cornerradius, O.y + height/2)
    p2end    = Point(O.x - width/2, O.y + height/2 - cornerradius)

    p3center = Point(O.x - width/2 + cornerradius, O.y - height/2 + cornerradius) # top left
    p3start  = Point(O.x - width/2, O.y - height/2 + cornerradius)
    p3end    = Point(O.x - width/2 + cornerradius, O.y - height/2)

    p4center = Point(O.x + width/2 - cornerradius, O.y - height/2 + cornerradius) # top right
    p4start  = Point(O.x + width/2 - cornerradius, O.y - height/2)
    p4end    = Point(O.x + width/2, O.y - height/2 + cornerradius)

    newpath()
    move(Point(O.x + width/2, O.y))
    line(p1start)
    arc(p1center, cornerradius, 0, pi/2, :none)
    line(p1end)
    line(p2start)

    arc(p2center, cornerradius, pi/2, pi, :none)
    line(p2end)
    line(p3start)

    arc(p3center, cornerradius, pi, (3pi)/2, :none)
    line(p3end)
    line(p4start)

    arc(p4center, cornerradius, (3pi)/2, 2pi, :none)
    line(p4end)

    closepath()
    do_action(action)
    grestore()
end

"""
    ngon(x, y, radius, sides=5, orientation=0, action=:none;
        vertices=false, reversepath=false)

Draw a regular polygon centered at point `centerpos`.
"""
function ngon(x::Real, y::Real, radius::Real, sides::Int=5, orientation=0.0, action=:none;
              vertices=false,
              reversepath=false)
    ptlist = [Point(x+cos(orientation + n * 2pi/sides) * radius,
                    y+sin(orientation + n * 2pi/sides) * radius) for n in 1:sides]
    if !vertices
        poly(ptlist, action, close=true, reversepath=reversepath)
    end
    return ptlist
end

"""
    ngon(centerpos, radius, sides=5, orientation=0, action=:none;
        vertices=false,
        reversepath=false)

Draw a regular polygon centered at point `centerpos`.

Find the vertices of a regular n-sided polygon centered at `x`, `y` with
circumradius `radius`.

The polygon is constructed counterclockwise, starting with the first vertex
drawn below the positive x-axis.

If you just want the raw points, use keyword argument `vertices=true`, which
returns the array of points. Compare:

```julia
ngon(0, 0, 4, 4, 0, vertices=true) # returns the polygon's points:

    4-element Array{Luxor.Point, 1}:
    Luxor.Point(2.4492935982947064e-16, 4.0)
    Luxor.Point(-4.0, 4.898587196589413e-16)
    Luxor.Point(-7.347880794884119e-16, -4.0)
    Luxor.Point(4.0, -9.797174393178826e-16)
```

whereas

```
ngon(0, 0, 4, 4, 0, :close) # draws a polygon
```
"""
ngon(centerpoint::Point, radius, sides::Int=5, orientation=0.0, action=:none; kwargs...) =
    ngon(centerpoint.x, centerpoint.y, radius, sides, orientation, action; kwargs...)

"""
    ngonside(centerpoint::Point, sidelength::Real, sides::Int=5, orientation=0,
        action=:none; kwargs...)

Draw a regular polygon centered at `centerpoint` with `sides` sides of length `sidelength`.
"""
function ngonside(centerpoint::Point, sidelength::Real, sides::Int=5, orientation=0,
    action=:none; kwargs...)
    radius = 0.5 * sidelength * csc(pi/sides)
    ngon(centerpoint, radius, sides, orientation, action; kwargs...)
end

"""
    star(xcenter, ycenter, radius, npoints=5, ratio=0.5, orientation=0, action=:none;
        vertices = false,
        reversepath=false)

Make a star. `ratio` specifies the height of the smaller radius of the star relative to the
larger.

Use `vertices=true` to return the vertices of a star instead of drawing it.
"""
function star(x::Real, y::Real, radius::Real, npoints::Int=5, ratio::Real=0.5,
    orientation=0, action=:none;
    vertices = false,
    reversepath=false)
    outerpoints = [Point(x+cos(orientation + n * 2pi/npoints) * radius,
                         y+sin(orientation + n * 2pi/npoints) * radius) for n in 1:npoints]
    innerpoints = [Point(x+cos(orientation + (n + 1/2) * 2pi/npoints) * (radius * ratio),
                         y+sin(orientation + (n + 1/2) * 2pi/npoints) * (radius * ratio)) for n in 1:npoints]
    result = Point[]
    for i in eachindex(outerpoints)
        push!(result, outerpoints[i])
        push!(result, innerpoints[i])
    end
    if reversepath
        result = reverse(result)
    end
    if !vertices
        poly(result, action, close=true)
    end
    return result
end

"""
    star(center, radius, npoints=5, ratio=0.5, orientation=0, action=:none;
        vertices = false, reversepath=false)

Draw a star centered at a position:
"""
function star(centerpoint::Point, radius::Real, npoints::Int=5, ratio::Real=0.5, orientation=0,
              action=:none;
              vertices=false,
              reversepath=false)
    star(centerpoint.x, centerpoint.y, radius, npoints, ratio, orientation, action;
         vertices = vertices, reversepath=reversepath)
end

"""
    cropmarks(center, width, height)

Draw cropmarks (also known as trim marks).
"""
function cropmarks(center, width, height)
    gap = 5
    crop = 15
    gsave()
    setcolor("black")
    setline(0.5)
    setdash("solid")
    # horizontal top left
    line(Point(-width/2 - gap - crop, -height/2),
         Point(-width/2 - gap, -height/2),
         :stroke)

    # horizontal bottom left
    line(Point(-width/2 - gap - crop, height/2),
         Point(-width/2 - gap, height/2),
         :stroke)

    # horizontal top right
    line(Point(width/2 + gap, -height/2),
         Point(width/2 + gap + crop, -height/2),
         :stroke)

    # horizontal bottom right
    line(Point(width/2 + gap, height/2),
         Point(width/2 + gap + crop, height/2),
         :stroke)

    # vertical top left
    line(Point(-width/2, -height/2 - gap - crop),
         Point(-width/2, -height/2 - gap),
         :stroke)

    # vertical bottom left
    line(Point(-width/2, height/2 + gap),
         Point(-width/2, height/2 + gap + crop),
         :stroke)

    # vertical top right
    line(Point(width/2, -height/2 - gap - crop),
         Point(width/2, -height/2 - gap),
         :stroke)

    # vertical bottom right
    line(Point(width/2, height/2 + gap),
         Point(width/2, height/2 + gap + crop),
         :stroke)

    grestore()
end


text:
using H3.API # GeoCoord geoToH3 kRing h3ToGeoBoundary

base = geoToH3(GeoCoord(deg2rad(0), deg2rad(0)), 5)
rings = kRing(base, 1)

x = Vector{Float64}()
y = Vector{Float64}()
for boundary in h3ToGeoBoundary.(rings), geo in boundary
    push!(x, geo.lon) # 經度
    push!(y, geo.lat) # 緯度
end

using UnicodePlots # scatterplot
@info :plot scatterplot(x, y)


text:
@testset "Strings" begin

    @testset "Strings: Is Palindrome" begin
        s = "AA"     # A palindrome
        @test is_palindrome(s) == true
        s = "ABC"     # Not a palindrome
        @test is_palindrome(s) == false
        s = "Statistics"    # Not a palindrome
        @test is_palindrome(s) == false
        s = "Stats"    # A palindrome
        @test is_palindrome(s) == true
        s = "Racecar"      # A palindrome
        @test is_palindrome(s) == true
        s = "Hello"      # Not a palindrome
        @test is_palindrome(s) == false
    end

    @testset "Strings: Detect Anagrams" begin
        s = "anagram"    # No matches
        samples = ["grammar", "tutor", "kilogram"]
        @test detect_anagrams(s, samples) == []
        s = "nose"  # Matches words with different case
        samples = ["Eons", "ONES"]
        @test detect_anagrams(s, samples) == ["Eons", "ONES"]
        s = "listen"  # Does not include the same word
        samples = ["LiSten", "enlist"]
        @test detect_anagrams(s, samples) == ["enlist"]
    end

    @testset "Strings: KMP SubString Search" begin
        # contain sub string
        string = "seems like kmp search works"
        sub_string = "seems like kmp search"
        @test contain_substring_with_kmp(string, sub_string, false) == true
        string = "ABABDABACDABABCABAB"
        sub_string = "ABABCABAB"
        @test contain_substring_with_kmp(string, sub_string, false) == true
        string = "abcxabcdabcdabcy"
        sub_string = "abcdabcy"
        @test contain_substring_with_kmp(string, sub_string, false) == true
        # does not contain sub string
        string = "ABABDABACDABABCABAB"
        sub_string = "X"
        @test contain_substring_with_kmp(string, sub_string, false) == false
        string = "abcxabcdabcdabcy"
        sub_string = "so this"
        @test contain_substring_with_kmp(string, sub_string, false) == false
        # ignore cases
        string = "SeEms Like IgNOrE CaSe Work"
        sub_string = "seems like ignore case work"
        @test contain_substring_with_kmp(string, sub_string, true) == true
        string = "123 456 AbC"
        sub_string = "123 456 ABC"
        @test contain_substring_with_kmp(string, sub_string, true) == true
        string = "abcdefg"
        sub_string = "ABCDEFG"
        @test contain_substring_with_kmp(string, sub_string, true) == true
    end
end

max_stars_repo_name: frankschmitt/Julia

max_issues_repo_name: frankschmitt/Julia

max_forks_repo_name: frankschmitt/Julia


text:
# This file was generated, do not modify it. # hide
data = select(boston, [:Rad, :Tax])
schema(data)


text:
@testset "issetequal" begin
    v1 = [1,2,3]
    v2 = [3,2,1]
    s = Set([1,2,3])
    k = keys(Dict(1=>1, 2=>2, 3=>3))

    sets = [v1, v2, s, k]
    for s1 in sets
        for s2 in sets
            @test issetequal(s1, s2)
        end
    end

    v1_bad1 = [1,2,3,4]
    v2_bad1 = [4,3,2,1]
    s_bad1 = Set([1,2,3,4])
    k_bad1 = keys(Dict(1=>1, 2=>2, 3=>3, 4=>4))

    v1_bad2 = [1,2]
    v2_bad2 = [2,1]
    s_bad2 = Set([1,2])
    k_bad2 = keys(Dict(1=>1, 2=>2))

    v1_bad3 = [2,3,4]
    v2_bad3 = [4,3,2]
    s_bad3 = Set([2,3,4])
    k_bad3 = keys(Dict(2=>2, 3=>3, 4=>4))

    badsets = [v1_bad1, v2_bad1, s_bad1, k_bad1,
               v1_bad2, v2_bad2, s_bad2, k_bad2,
               v1_bad3, v2_bad3, s_bad3, k_bad3]

    for s1 in sets
        for s2 in badsets
            @test !issetequal(s1, s2)
        end
    end

    for s1 in badsets
        for s2 in sets
            @test !issetequal(s1, s2)
        end
    end
end


text:
import Base: size, eachindex, getindex, view, ==, eltype, convert
import Distances: pairwise
export ColsAreObs, BlockData

################################## Basic matrix data type ##################################

"""
    ColsAreObs{T, TX<:AbstractMatrix}

A lightweight box for an `AbstractMatrix` to make it behave like a vector of vectors.
"""
struct ColsAreObs{T, TX<:AbstractMatrix{T}} <: AbstractVector{Vector{T}}
    X::TX
    ColsAreObs(X::TX) where {T, TX<:AbstractMatrix{T}} = new{T, TX}(X)
end

@inline ==(D1::ColsAreObs, D2::ColsAreObs) = D1.X == D2.X
@inline size(D::ColsAreObs) = (size(D.X, 2),)
@inline getindex(D::ColsAreObs, n::Int) = D.X[:, n]
@inline getindex(D::ColsAreObs, n) = ColsAreObs(D.X[:, n])
@inline view(D::ColsAreObs, n::Int) = view(D.X, :, n)
@inline view(D::ColsAreObs, n) = ColsAreObs(view(D.X, :, n))
@inline eltype(D::ColsAreObs{T}) where T = Vector{T}

################################ Fancy block data set type #################################

"""
    BlockData{T, TV<:AbstractVector{T}, TX<:AbstractVector{TV}} <: AbstractVector{T}

A strictly ordered collection of `AbstractVector`s, representing a ragged array of data.
"""
struct BlockData{T, V<:AbstractVector{<:T}} <: AbstractVector{T}
    X::Vector{V}
end
BlockData(X::Vector{V}) where {T, V<:AbstractVector{T}} = BlockData{T, V}(X)
BlockData(X::Vector{AbstractVector}) = BlockData{Any, AbstractVector}(X)
@inline ==(D1::BlockData, D2::BlockData) = D1.X == D2.X
@inline size(D::BlockData) = (sum(length, D.X),)

@inline blocks(X::BlockData) = X.X
function getindex(D::BlockData, n::Int)
    b = 1
    while n > length(D.X[b])
        n -= length(D.X[b])
        b += 1
    end
    return D.X[b][n]
end
function getindex(D::BlockData, n::BlockVector{<:Integer})
    @assert eachindex(D) == n
    return D
end
@inline view(D::BlockData, b::Int, n) = view(D.X[b], n)
@inline eltype(D::BlockData{T}) where T = T
function eachindex(D::BlockData)
    lengths = map(length, blocks(D))
    # return 1:sum(length, blocks(D))
    return BlockArray(1:sum(lengths), lengths)
    # return BlockData(lengths)
end

convert(::Type{BlockData}, x::BlockData) = x
convert(::Type{BlockData}, x::AbstractVector) = BlockData([x])


text:
# Reference implementation

module Reference

# todo: simplify to better serve as a highly trusted reference implementation
#       goal is to make it simple and easy to verify without worrying too much
#       about computational speed or memory use

using OffsetArrays, ImageFiltering, LinearAlgebra

sosdiff(a::Number,b::Number) = abs2(a-b)
sosdiff(A,B) = sum(ab -> sosdiff(ab...),zip(A,B))

hard(x, beta) = abs(x) < beta ? zero(x) : x
_obj(zlk,λ) = sum(z -> (abs(z) < sqrt(2λ) ? abs2(z)/2 : λ), zlk)

function CAOL(x,λ,H0,R,maxiters,tol)
    @assert H0'H0 ≈ (1/prod(R))*I
    K = size(H0,2)

    # Form padded images
    xpad = [padarray(xl,Pad(:circular,ntuple(_->0,ndims(xl)),R)) for xl in x]

    # Initialize filters
    H = copy(H0)
    h = [reshape(view(H,:,k),map(n->1:n,R)) for k in 1:K]
    Hprev = similar(H)  # for stopping condition

    # Initialize temporary variables
    zlk = similar(first(x),map(n->0:n-1,size(first(x))))
    ΨZ = similar(H)
    ψz = [reshape(view(ΨZ,:,k),map(n->1:n,R)) for k in 1:K]
    ψztemp = similar(first(ψz))
    HΨZ = similar(H,K,K)
    UVt = HΨZ

    # Initialize trace of H's, objectives and Hdiff
    Htrace     = Array{typeof(H0)}(undef,maxiters)
    objtrace   = OffsetArray(fill(NaN,maxiters),-1)
    Hdifftrace = fill(NaN,maxiters)

    for t in 1:maxiters
        copyto!(Hprev,H)

        # Compute objective and update ΨZ
        objtrace[t-1] = zero(objtrace[t-1])
        fill!(ΨZ,zero(eltype(ΨZ)))
        for xpadl in xpad, k in 1:K
            imfilter!(zlk,xpadl,(h[k],),NoPad(),Algorithm.FIR())
            objtrace[t-1] += _obj(zlk,λ)
            zlk .= hard.(zlk,sqrt(2λ))
            imfilter!(ψztemp,xpadl,(zlk,),NoPad(),Algorithm.FIR())
            ψz[k] .+= ψztemp
        end

        # Update filter via polar factorization
        mul!(HΨZ,H0',ΨZ)
        F = svd!(HΨZ)
        mul!(UVt,F.U,F.Vt)
        mul!(H,H0,UVt)

        # Store trace of H
        Htrace[t] = copy(H)

        # Terminate
        Hdifftrace[t] = sqrt(sosdiff(Hprev,H) / (K/prod(R)))
        Hdifftrace[t] <= tol && break
    end

    niters = count(o -> !isnan(o),objtrace)
    return H, Htrace[1:niters], objtrace[0:niters-1], Hdifftrace[1:niters]
end

end


text:
using MissingsAsFalse
using Test

@testset "scalar equality and other comparisons" begin
    x = missing

    b = @mfalse x == 5
    @test b == false

    b = @mfalse x > 5
    @test b == false

    b = @mfalse x >= 5
    @test b == false

    b = @mfalse x < 5
    @test b == false

    b = @mfalse x <= 5
    @test b == false
end

@testset "array equality and other comparisons" begin
    x = [1, missing]

    y = [1, 3]

    b = @mfalse x .== y
    @test b == [true, false]

    b = @mfalse x .> y
    @test b == [false, false]

    b = @mfalse x .>= y
    @test b == [true, false]

    b = @mfalse x .< y
    @test b == [false, false]

    b = @mfalse x .<= y
    @test b == [true, false]

    x = [1 missing; missing 3]
    y = [1 2; 4 3]
    b = @mfalse x .== y

    @test b == [true false; false true]
end

@testset "if and ifelse" begin
    x = missing

    b = @mfalse x == 1 ? 100 : 200

    @test b == 200

    b = @mfalse begin
        if x == 5
            100
        else
            200
        end
    end

    @test b == 200

    b = @mfalse begin
        if false
            100
        elseif x == 1
            200
        else
            300
        end
    end

    @test b == 300

    b = @mfalse if false
            100
        elseif x == 1
            200
        else
            300
    end

    @test b == 300
end

@testset "indexing" begin
    y = [1, 2, 3]
    x = [true, false, true]
    xm = [true, false, missing]
    xi = [1, 3]

    b = @mfalse y[x]
    @test b == [1, 3]

    b = @mfalse y[xm]
    @test b == [1]

    b = @mfalse y[xi]
    @test b == [1, 3]

    y = [1 2; 3 4]
    x = [true missing; missing true]
    b = @mfalse y[x]
    @test b == [1, 4]
end

@testset "&& and ||" begin
    x = missing

    b = @mfalse if (x || true)
        1
    else
        2
    end

    @test b == 1

    b = @mfalse if (x && true)
        1
    else
        2
    end

    @test b == 2

    b = @mfalse (x && missing)
    @test b = = false

    b = @mfalse (x || missing)
    @test b == false
end


text:
using PyPlot, FileIO
include("util.jl")
"""
    animated_gif(stimulus...; filename="default.gif", verbose=0, kwargs...)

Creates an animated gif of the given stimuli (can animate more than one at a time for
side-by-side comparison). Super hack-y: Uses `PyPlot`'s `imshow` function for each frame of
the stimulus, writes them to separate `.gif` files, then uses a system call to `convert` or
the `FileIO` package to create the animated gif. Will delete the individual frames after
it's done, and will do its best to be graceful about this (i.e. if it's interrupted, that
sort of thing).

Note that it will remove any filename extensions from `filename` using `remove_extension`
and then append ".gif". In particular, if there are any `'.'` characters in `filename`, make
sure it ends with `.gif`

Returns `success, status` where `success` is a boolean indicated success or failure of the
process to produce an animated gif, and `status` is an array of strings and `Exception`s
representing status messages produced throughout (e.g. warnings about which frames got
skipped, that sort of thing).

"""
function animated_gif(stimulus...; filename="default.gif", verbose=0,
    kwargs...)

    dkwargs = Dict(kwargs)

    ########################################
    #### Handle filename stuff
    ########################################
    floc = dirname(abspath(filename))
    fname_root = remove_extension(basename(filename))
    temp_dir = joinpath(floc, fname_root, "temp")
    gif_filename = joinpath(floc, fname_root * ".gif")
    intermediate_extension = pop!(dkwargs, :temp_ext, ".png") # since apparently pyplot can't write GIFs

    method=pop!(dkwargs, :method, "ImageMagick")

    ########################################
    #### Get animation properties
    ########################################
    start_frame = pop!(dkwargs, :start_frame, 1)
    end_frame = pop!(dkwargs, :end_frame, minimum(map(n_frames,stimulus)))
    frame_range = pop!(dkwargs, :frame_range, start_frame:end_frame)
    loop = pop!(dkwargs, :loop, 0)
    # Framerate: in order, check for :fps, :frame_time_s
    fps = pop!(dkwargs, :fps, 60)
    frame_time_s = pop!(dkwargs, :frame_time_s, 1/fps)
    # since frame_time_s is ultimately the winner, overwrite fps
    fps = 1/frame_time_s
    frame_time_hundredths = round(Int,100frame_time_s)

    ########################################
    #### Get pyplot options
    ########################################
    cmap = pop!(dkwargs, :cmap, "gray")
    aspect = pop!(dkwargs, :aspect, "equal")
    cbar = pop!(dkwargs, :colorbar, true)
    tight = pop!(dkwargs, :tight_layout, true)
    normalize = pop!(dkwargs, :normalize, false)
    layout_x = ceil(Int, sqrt(length(stimulus)))
    layout_y = ceil(Int, length(stimulus)/layout_x)
    titles = pop!(dkwargs, :titles, ["Stimulus $i" for i in 1:length(stimulus)])

    ########################################
    #### State setting things up
    ########################################
    # TODO this is dangerous when frame_range is large!
    image_arrays = [frame_image(S, frame_range) for S in stimulus]

    if normalize
        # normalize across stimuli as well as across frames
        vmin = fill(minimum(map(minimum,image_arrays)), size(image_arrays))
        vmax = fill(maximum(map(maximum,image_arrays)), size(image_arrays))
    else
        # normalize frames so that a given stimulus uses the same range for each frame.
        vmin = map(minimum, image_arrays)
        vmax = map(maximum, image_arrays)
    end

    success = false
    status = []

    try
        if verbose > 0
            println("animated_gif: Making path $temp_dir")
        end
        mkpath(temp_dir)

        # for frame_idx in 1:length(frame_range)
        if verbose > 0
            println("animated_gif: Generating individual frames. Expecting $(length(frame_range)) frames at " * @sprintf("%2.1f",fps) * " fps")
            if verbose > 1
                print("animated_gif: [")
            end
        end
        for (frame_idx, frame_number) in enumerate(frame_range)
            frame_filename = "$fname_root-" * @sprintf("%04d",frame_idx) * intermediate_extension

            fig = figure("Frame $frame_idx", tight_layout=true)
            # for stim_idx in 1:length(image_arrays)
            for (stim_idx,(S,img_arr)) in enumerate(zip(stimulus,image_arrays))
                subplot("$layout_x$layout_y$stim_idx")
                imshow(img_arr[:,:,frame_idx], cmap=cmap, aspect=aspect, vmin=vmin[stim_idx], vmax=vmax[stim_idx])
                if cbar
                    colorbar()
                end
                title(titles[stim_idx])
                # TODO could add more options for xticks, yticks, that sort of thing later

                # for now, clear ticks
                xticks()
                yticks()

                # for now, xlabel is "t = X s"
                xlabel("t = " * @sprintf("%0.3f", index_to_time(S, frame_number)) * " s")
            end
            savefig(joinpath(temp_dir, frame_filename))
            close(fig)
            if verbose > 1
                print(".")
            end
        end
        if verbose > 1
            println("]")
        end

        if method == "ImageMagick"
            if verbose > 0
                println("animaged_gif: loading files for ImageMagick")
                print("animated_gif: [")
            end
            frame1 = load(joinpath(temp_dir, "$fname_root-0001$intermediate_extension"))
            A = Array{eltype(frame1)}(size(frame1)...,length(frame_range))
            A[:,:,1] = frame1
            for fn in 2:length(frame_range)
                A[:,:,fn] = load(joinpath(temp_dir, "$fname_root-" * @sprintf("%04d",fn) * intermediate_extension))
                if verbose > 0
                    print(".")
                end
            end
            if verbose > 0
                println("]")
                print("animated_gif: saving gif...")
                save(joinpath(floc,gif_filename), A, fps=fps)
                println("done")
                println("Created file $(joinpath(floc,gif_filename))")
            end
            success = true
        else
            # default: do a system call to use convert
            if verbose > 0
                print("animated_gif: Running `convert`...")
            end
            convert_cmd = `convert -delay $frame_time_hundredths -loop $loop '$(joinpath(temp_dir,fname_root))-*$intermediate_extension' $(joinpath(floc,gif_filename))`
            run(convert_cmd)
            if verbose > 0
                println("done.")
                println("Created file $(joinpath(floc,gif_filename))")
            end
            success = true
        end
    catch except
        if verbose > 0
            println()
            println("animated_gif: Encountered exception(s), beginning clean up...")
        end
        success = false
        push!(status, except)
    finally
        if verbose > 0
            print("animated_gif: Cleaning up. ")
        end
        close("all")
        if verbose > 0
            print("Closed figures. ")
        end
        rm(joinpath(floc, fname_root), force=true, recursive=true)
        if verbose > 0
            println("Removed directory $(joinpath(floc, fname_root))")
        end
    end
    return success, status
end