diff --git a/.gitignore b/.gitignore index d16917c8..cc7e5064 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,24 @@ *.o Depend.list +.project +.kdev4/ +source.kdev4 + + # Don't track intermediary files from building the manual -doc/*.aux -doc/*.fdb_latexmk -doc/*.fls -doc/*.log -doc/*.out -doc/*.toc +extras/doc-latex/*.aux +extras/doc-latex/*.fdb_latexmk +extras/doc-latex/*.fls +extras/doc-latex/*.log +extras/doc-latex/*.out +extras/doc-latex/*.gz +extras/doc-latex/*.toc # Don't track the STAR binary once it has being built source/STAR +.DS_Store +*.xcworkspacedata +*.pbxproj +*.plist +*.xcuserstate diff --git a/CHANGES.md b/CHANGES.md index fdb36747..0f049d55 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,214 @@ +* Issue #1223: fixed the N_unmapped value reported in ReadsPerGene.out.tab. The single-end (i.e. partially mapped alignment are not excluded from N_unmapped. +* Issues #535, #1350: fixed a long-standing problem that resulted in a seg-fault whem mapping to the rabbit genome. +* Issue #1316: fixed the seg-fault which occurred if --soloType CB_samTagOut and --soloCBwhitelist None are used together. +* Changed Solo summary statistics outputs in Barcodes.stats and Features.stats files. +* Implemented --soloCBmatchWLtype ParseBio_ED3 to allow multiple mismatches and one insertion+deletion for --soloType CB_UMI_Complex. +* Implemented Solo BAM tags gx gn: output ';'-separated gene IDs and names for both unique- and multi-gene reads. Note that GX/GN tags are used to output gene ID/name for unique-gene reads. +* Changed Solo BAM tags GX GN behavior: for missing values, "-" is output instead of omitting the tag. +* Changed Solo BAM tags output for multiple --soloFeatures: now the first feature on the list is used for GX,GN,XB,UB tags. +* Changed Solo SJ behavior: it no longer depend on the whether the alignment is concordant to a Gene. +* Implemented --soloFeatures GeneFull_ExonOverIntron GeneFull_Ex50pAS options which prioritize exonic over intronic overlaps for pre-mRNA counting. +* Fixed a bug that resulted in slightly different solo counts if --soloFeatures Gene and GeneFull were used together with --soloCBmatchWLtype 1MM_multi_pseudocounts option. +* Fixed a bug introduced in 2.7.9a for --quantMode TranscriptomeSAM output that resulted in both mapped and unmapped output for some reads. Many thanks to Diane Trout (@Caltech) for helping to track this bug. +* Issue #1177: throw an error in case the BAM file does not contain NH and AS tags for duplication removal jobs (--runMode inputAlignmentsFromBAM --bamRemoveDuplicatesType UniqueIdenticalNotMulti). +* Issue #1262: fixed the bug that prevented EM matrix output when only EM option is specified in --soloMultiMappers. +* Issue #1230: fixed the bug that caused seg-faults for --runMode soloCellFiltering runs. +* Added script extras/scripts/soloCountMatrixFromBAM.awk to re-create Solo count matrix from the BAM output. + +STAR 2.7.9a --- 2021/05/05 ::: STARsolo updates +===================================================== +**Major updates:** +* STARsolo can perform counting of multi-gene (multi-mapping) reads with --soloMultiMappers EM [Uniform Rescue PropUnqiue] options. +* PR #1163: [SIMDe](https://github.com/simd-everywhere/simde) takes care of correct SIMD extensions based on -m g++ flag: compilation option CXXFLAGS_SIMD is preset to -mavx2, but can be to the desired target architecture. Many thanks to Michael R. Crusoe @mr-c, Evan Nemerson @nemequ and Steffen Möller @smoe! + +**New options and features:** +* New option: --soloUMIfiltering MultiGeneUMI_All to filter out all UMIs mapping to multiple genes (for uniquely mapping reads) +* New script extras/scripts/calcUMIperCell.awk to calculate total number of UMIs per cell and filtering status from STARsolo matrix.mtx +* New option: --outSJtype None to omit outputting splice junctions to SJ.out.tab +* Simple script to convert BED spliced junctions (SJ.out.tab) to BED12 for UCSC display: extras/scripts/sjBED12.awk +* PR #1164: SOURCE_DATE_EPOCH to make the build more reproducible +* PR #1157: print STAR command line and version information to stdout + +**Changes in behavior:** +* Minor changes to statistics output (Features.csv and Summary.csv) to accomodate multimappers. +* Modified option: ---limitIObufferSize now requires two numbers - separate sizes for input and output buffers + +**Bug fixes** +* PR #1156: clean opal/opal.o +* Issue #1166: seg-fault for STARsolo --soloCBwhitelist None (no whitelist) with barcodes longer than 16b +* Issue #1167: STARsolo CR/UR SAM tags are scrambled in TranscriptomeSAM file Aligned.toTranscriptome.out.bam. This bug appeared in 2.7.7a. +* Issue #1177: Added file checks for the --inputBAMfile . +* Issue #1180: Output the actual number of alignments in NH attributes even if --outSAMmultNmax is set to a smaller value. +* Issue #1190: Allow GX/GN output for non-STARsolo runs. +* Issue #1220: corrupt SAM/BAM files for --outFilterType BySJout. The bug was introduced with the chnages in 2.7.7a. +* Issue #1211: scrambled CB tags in BAM output for --soloCBwhitelist None --soloFeatures Gene GeneFull. +* Fixed a bug causing seg-faults with --clipAdapterType CellRanger4 option. + +STAR 2.7.8a --- 2021/02/20 ::: Major STARsolo updates +===================================================== + +**Major new features:** +* ```--runMode soloCellFiltering``` option for cell filtering (calling) of the raw count matrix, without re-mapping +* Input from SAM/BAM for STARsolo, with options ```--soloInputSAMattrBarcodeSeq``` and ```--soloInputSAMattrBarcodeQual``` to specify SAM tags for the barcode read sequence and qualities +* ```--clipAdapterType CellRanger4``` option for 5' TSO adapter and 3' polyA-tail clipping of the reads to better match CellRanger >= 4.0.0 mapping results +* ```--soloBarcodeMate``` to support scRNA-seq protocols in which one of the paired-end mates contains both barcode sequence and cDNA (e.g. 10X 5' protocol) + +**New options:** +* ```--soloCellFilter EmptyDrops_CR``` option for cell filtering (calling) nearly identical to that of CellRanger 3 and 4 +* ```--readFilesSAMattrKeep``` to specify which SAM attributes from the input SAM to keep in the output +* ```--soloUMIdedup 1M_Directional_UMItools``` option matching the "directional" method in UMI-tools Smith, Heger and Sudbery (Genome Research 2017) +* ```--soloUMIdedup NoDedup``` option for counting reads per gene, i.e. no UMI deduplication +* ```--soloUMIdedup 1MM_CR``` option for 1 mismatch UMI deduplication similar to CellRanger >= 3.0 +* ```--soloUMIfiltering MultiGeneUMI_CR``` option filters lower-count UMIs that map to more than one gene matching CellRanger >= 3.0 +* ```--soloCBmatchWLtype 1MM_multi_Nbase_pseudocounts``` options which allows 1MM multimatching to WL for barcodes with N-bases (to better match CellRanger >= 3.0) + +**Changes in behavior:** +* The UMI deduplication/correction specified in ```--soloUMIdedup``` is used for statistics output, filtering and UB tag in BAM output. +* If UMI or CB are not defined, the UB and CB tags in BAM output will contain "-" (instead of missing these tags). +* For ```--soloUMIfiltering MultiGeneUMI``` option, the reads with multi-gene UMIs will have UB tag "-" in BAM output. +* Different ```--soloUMIdedup``` counts, if requested, are recorded in separate .mtx files. +* Cell-filtered Velocyto matrices are generated using Gene cell filtering. +* Velocyto spliced/unspliced/ambiguous counts are reported in separate .mtx files. +* Read clipping options ```--clip*``` now require specifying the values for all read mates, even if they are identical. + +**Bug fixes:** +* Issue #1107: fixed a bug causing seg-fault for ```--soloType SmartSeq``` with only one (pair of) fastq file(s) +* Issue #1129: fixed an issue with short barcode sequences and ```--soloBarcodeReadLength 0``` +* Issue #796: Fixed a problem with GX/GN tag output for ```--soloFeatures GeneFull``` option +* PR: #1012: fix the bug with ```--soloCellFilter TopCells``` option +* Fixed an issue that was causing slightly underestimated value of Q30 'Bases in RNA read' in ```Solo.out/Gene/Summary.csv``` + +STAR 2.7.7a --- 2020/12/28 +========================== +**Major new feature: STARconsensus: mapping RNA-seq reads to consensus genome.** +* Insert (consensus) variants from a VCF file into the reference genome at the genome generation step with ```--genomeTransformVCF Variants.vcf --genomeTransformType Haploid``` +* Map to the transformed genome. Alignments (SAM/BAM) and spliced junctions (SJ.out.tab) can be transformed back to the original (reference) coordinates with ```--genomeTransformOutput SAM and/or SJ``` + +**Minor bug fixes:** +* Deprecated ```--genomeConsensusFile``` option. Please use ```--genomeTransformVCF``` and ```--genomeTransformType``` options instead. +* Issue #1040: fixed a bug causing rare seg-faults for paired-end --soloType SmartSeq runs. +* Issue #1071: fixed a bug that can cause a crash for STARsolo runs with a small number of cells. + +STAR 2.7.6a --- 2020/09/19 +========================== +**Major new feature:** +Output multimapping chimeric alignments in BAM format using +```--chimMultimapNmax N>1 --chimOutType WithinBAM --outSAMtype BAM Unsorted [and/or] SortedByCoordinate``` +Many thanks to Sebastian @suhrig who implemented this feature! +More detailed description from Sebastian in PR #802. + +**Minor features and bug fixes:** +* Issue #1008: fixed the problem with Unmapped.out.mate? output for --soloType CB_samTagOut output. +* PR # 1012: fixed the bug with --soloCellFiltering TopCells option. +* Issue #786: fixed the bug causing the *Different SJ motifs problem* for overlapping mates. +* Issue #945: GX/GN can be output for all --soloType, as well as for non-solo runs. + +STAR 2.7.5c --- 2020/08/16 +========================== +Bug-fix release. +---------------- + +* Issue #988: proceed reading from GTF after a warning that exon end is past chromosome end. +* Issue #978: fixed corrupted transcriptInfo.tab in genome generation for cases where GTF file contains extra chromosomes not present in FASTA files. +* Issue #945: otuput GX/GN for --soloFeatures GeneFull . +* Implemented removal of control characters from the ends of input read lines, for compatibility with files pre-processed on Windows. + +STAR 2.7.5b --- 2020/08/01 +========================== +Bug-fix release. +---------------- + +* Issue #558: Fixed a bug that can cause a seg-fault in STARsolo run with paired-end reads that have protruding ends. +* Issue #952: Increased the maximum allowed length of the SAM tags in the input SAM files. +* Issue #955: fixed seg-fault-causing bug for --soloFeatures SJ option. +* Issue #963: When reading GTF file, skip any exons that extend past the end of the chromosome, and give a warning. +* Issue #965: output genome sizes with and without padding into Log.out. +* Docker build: switched to debian:stable-slim in the Dockerfile. +* --soloType CB_samTagOut now allows output of (uncorrected) UMI sequences and quality scores with SAM tags UR and UY. +* Throw an error if FIFO file cannot be created on non-Linux partitions. + +STAR 2.7.5a 2020/06/16 +====================== +**Major new features:** +* Implemented STARsolo quantification for Smart-seq with --soloType SmartSeq option. +* Implemented --readFilesManifest option to input a list of input read files. + +**Minor features and bug fixes:** +* Change in STARsolo SJ output behavior: junctions are output even if reads do not match genes. +* Fixed a bug with solo SJ output for large genomes. +* N-characters in --soloAdapterSequence are not counted as mismatches, allowing for multiple adapters (e.g. ddSeq). +* SJ.out.tab is sym-linked as features.tsv for Solo SJ output. +* Issue #882: 3rd field is now optional in Solo Gene features.tsv with --soloOutFormatFeaturesGeneField3. +* Issue #883: Patch for FreeBSD in SharedMemory and Makefile improvements. +* Issue #902: Fixed seg-fault for STARsolo CB/UB SAM attributes output with --soloFeatures GeneFull --outSAMunmapped Within options. +* Issue #934: Fixed a problem with annotated junctions that was causing very rare seg-faults. +* Issue #936: Throw an error if an empty whitelist is provided to STARsolo. + +STAR 2.7.4a 2020/06/01 +====================== +Fixing multiple bugs and issues. +-------------------------------- + +**This version requires re-generation of the genome indexes** + +* Fixed the long-standing seg-fault problem for small genomes. +* Issue #784: Fixed a seg-fault in STARsolo for cases where no cell barcodes matched whitelist. +* Issue #798: Fixed the problem in Solo Q30 Bases in Summary.csv average (#798). +* Issue #843, #880: Throw an error if read file in --readFilesIn does not exist when using --readFilesCommand . +* Issue #864: Fixed seg-fault for STARsolo runs with very small number of reads or cells. +* Issue #881: Check if --genomeDir exists, create if necessary. +* Issue #882: Added 3rd column "Gene Expression" to solo features.tsv file for better compatibility with downstream tools. +* Issue #902: Fixed seg-fault for STARsolo CB/UB SAM attributes output with --soloFeatures GeneFull only option. +* Issue #907: Fixed the bug that prevented output of STARsolo GX/GN tags into the Aligned.out.bam if --quantMode TranscriptomeSAM is used. +* Issue #910: The output directory in --outFileNamePrefix is checked and created if it does not exist. +* If solo barcode read length is not checked (--soloBarcodeReadLength 0) and it is shorter than CB+UMI length, the barcode is padded with Ns and not counted. +* For genome generation runs, the Log.out file is moved into the --genomeDir directory. +* Fixed a bug with solo SJ output for large genomes. +* Implemented --seedMapMin option (previously hard-coded) to define minimum seed length. + +STAR 2.7.3a 2019/10/08 +====================== +Major new features in STARsolo +------------------------------ +* **Output enhancements:** + * Summary.csv statistics output for raw and filtered cells useful for quick run quality assessment. + * --soloCellFilter option for basic filtering of the cells, similar to the methods used by CellRanger 2.2.x. +* [**Better compatibility with CellRanger 3.x.x:**](docs/STARsolo.md#matching-cellranger-3xx-results) + * --soloUMIfiltering MultiGeneUMI option introduced in CellRanger 3.x.x for filtering UMI collisions between different genes. + * --soloCBmatchWLtype 1MM_multi_pseudocounts option, introduced in CellRanger 3.x.x, which slightly changes the posterior probability calculation for CB with 1 mismatch. +* [**Velocyto spliced/unspliced/ambiguous quantification:**](docs/STARsolo.md#velocyto-splicedunsplicedambiguous-quantification) + * --soloFeatures Velocyto option to produce Spliced, Unspliced, and Ambiguous counts similar to the [velocyto.py](http://velocyto.org/) tool developed by [LaManno et al](https://doi.org/10.1038/s41586-018-0414-6). This option is under active development and the results may change in the future versions. +* [**Support for complex barcodes, e.g. inDrop:**](docs/STARsolo.md#barcode-geometry) + * Complex barcodes in STARsolo with --soloType CB_UMI_Complex, --soloCBmatchWLtype --soloAdapterSequence, --soloAdapterMismatchesNmax, --soloCBposition,--soloUMIposition +* [**BAM tags:**](#bam-tags) + * CB/UB for corrected CellBarcode/UMI + * GX/GN for gene ID/name +* STARsolo most up-to-date [documentation](docs/STARsolo.md). + + +STAR 2.7.2d 2019/10/04 +====================== +* Fixed the problem with no header in Chimeric.out.sam + +STAR 2.7.2c 2019/10/02 +====================== +* Fixed the problem with no output to Chimeric.out.sam + +STAR 2.7.2b 2019/08/29 +====================== +Bug fixes in chimeric detection, contributed by Meng Xiao He (@mengxiao) +* Fix memory leak in handling chimeric multimappers: #721 +* Ensure chimeric alignment score requirements are consistently checked: #722,#723. + STAR 2.7.2a 2019/08/13 ====================== * Chimeric read reporting now requires that the chimeric read alignment score higher than the alternative non-chimeric alignment to the reference genome. The Chimeric.out.junction file now includes the scores of the chimeric alignments and non-chimeric alternative alignments, in addition to the PEmerged bool attribute. (bhaas, Aug 2019) * Fixed the problem with ALT=* in STAR-WASP. * Implemented extras/scripts/soloBasicCellFilter.awk script to perform basic filtering of the STARsolo count matrices. +* Fixed a bug causing rare seg-faults with for --peOverlap* options and chimeric detection. +* Fixed a problem in STARsolo with unmapped reads counts in Solo.out/*.stats files. +* Fixed a bug in STARsolo with counting reads for splice junctions. Solo.out/matrixSJ.mtx output is slighlty changed. +* Fixed the problem with ALT=* in VCF files for STAR-WASP. STAR 2.7.1a 2019/05/15 ====================== @@ -20,7 +226,6 @@ STAR 2.7.1a 2019/05/15 STAR 2.7.0f 2019/03/28 ====================== - * Fixed a problem in STARsolo with empty Unmapped.out.mate2 file. Issue #593. * Fixed a problem with CR CY UR UQ SAM tags in solo output. Issue #593. * Fixed problems with STARsolo and 2-pass. @@ -172,7 +377,7 @@ STAR 2.5.2b 2016/08/19 STAR 2.5.2a 2016/05/10 ====================== -* Fixed the "GstrandBit" problem. +* Fixed the "GstrandBit" problem. * Fixed a bug introduced in 2.5.1a that caused problems with single-end alignments output in some cases. * Fixed a bug that can cause STARlong seg-faults in rare cases. * Fixed a bug that caused output of unmapped mates for single end alignments even with --outSAMunmapped None . @@ -230,7 +435,7 @@ Major new features: ------------------- * Implemented on the fly insertion of the extra sequences into the genome indexes. * Implemented --outSAMmultNmax parameter to limit the number of output alignments for multimappers. -* Implemented --outMultimapperOrder Random option to output multiple alignments in random order. +* Implemented --outMultimapperOrder Random option to output multiple alignments in random order. This also randomizes the choice of the primary alignment. Parameter --runRNGseed can be used to set the random generator seed. With this option, the ordering of multi-mapping alignments of each read, and the choice of the primary alignment will vary from run to run, unless only one thread is used and the seed is kept constant. @@ -310,7 +515,7 @@ STAR 2.4.1a 2015/04/17 * Included link (submodule) to Brian Haas' STAR-Fusion code for detecting fusion transcript from STAR chimeric output: https://github.com/STAR-Fusion/STAR-Fusion * Included Gery Vessere's shared memory implementation for POSIX and SysV. To compile STAR with POSIX shared memory, use `make POSIXSHARED` * New option "--chimOutType WithinBAM" to include chimeric alignments together with normal alignments in the main (sorted or unsorted) BAM file(s). -* New option "--quantTranscriptomeBan Singleend" allows insertions, deletions ans soft-clips in the transcriptomic alignments, which are allowed by some expression quantification software (e.g. eXpress). +* New option "--quantTranscriptomeBan Singleend" allows insertions, deletions ans soft-clips in the transcriptomic alignments, which are allowed by some expression quantification software (e.g. eXpress). * New option "--alignEndsTypeExtension Extend5pOfRead1" to enforce full extension of the 5p of the read1, while all other ends undergo local alignment and may be soft-clipped. 2.4.0k 03/30/2015 @@ -434,8 +639,8 @@ Fixed problem with FASTA reads input. Fixed problem with compilation, samtools/ZLIB related. 2.3.1z9 06/19/2014 -2.3.1z8 -2.3.1z7 +2.3.1z8 +2.3.1z7 Fixed problems with transcriptomic output. Changed --sjdbFileChrStartEnd importing to allow direct import from SJ.out.tab @@ -454,7 +659,7 @@ Fixed chimeric output problems with --outFilterType BySJout option Added extra Log.out messages for multi-threaded jobs. 2.3.1z1 03/13/2014 -SAM header changes: +SAM header changes: removed "cl:" attribute from the @PG line, output it as a separate comment line added --outSAMheaderHD, --outSAMheaderPG, --outSAMheaderCommentFile options Added --outTmpDir, which set the path forSTAr temporary directory independent of --outFileNamePrefix @@ -550,4 +755,3 @@ Fixed possible issue which in some cases could have resulted in empty Chimeric.o Fixed incorrect processing of --sjdbGTFchrPrefix. 2.3.0e - diff --git a/README.md b/README.md index acf42ea7..a871e3fc 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,19 @@ -STAR 2.7 -======== +STAR 2.7.9a +========== Spliced Transcripts Alignment to a Reference -© Alexander Dobin, 2009-2019 +© Alexander Dobin, 2009-2021 https://www.ncbi.nlm.nih.gov/pubmed/23104886 AUTHOR/SUPPORT ============== -Alex Dobin, dobin@cshl.edu +Alex Dobin, dobin@cshl.edu
+https://github.com/alexdobin/STAR/issues
https://groups.google.com/d/forum/rna-star HARDWARE/SOFTWARE REQUIREMENTS ============================== * x86-64 compatible processors - * 64 bit Linux or Mac OS X + * 64 bit Linux or Mac OS X MANUAL ====== @@ -35,9 +36,9 @@ Download the latest [release from](https://github.com/alexdobin/STAR/releases) a ```bash # Get latest STAR source from releases -wget https://github.com/alexdobin/STAR/archive/2.7.2a.tar.gz -tar -xzf 2.7.2a.tar.gz -cd STAR-2.7.2a +wget https://github.com/alexdobin/STAR/archive/2.7.9a.tar.gz +tar -xzf 2.7.9a.tar.gz +cd STAR-2.7.9a # Alternatively, get STAR source using git git clone https://github.com/alexdobin/STAR.git @@ -51,17 +52,26 @@ Compile under Linux cd STAR/source make STAR ``` +For processors that do not support AVX extensions, specify the target SIMD architecture, e.g. +``` +make STAR CXXFLAGS_SIMD=sse +``` + Compile under Mac OS X ---------------------- ```bash # 1. Install brew (http://brew.sh/) -# 2. Install gcc with brew: +# 2. Install gcc with brew: $ brew install gcc --without-multilib # 3. Build STAR: +# run 'make' in the source directory # note that the path to c++ executable has to be adjusted to its current version +$cd source $make STARforMacStatic CXX=/usr/local/Cellar/gcc/8.2.0/bin/g++-8 +# 4. Make it availible through the terminal +$cp STAR /usr/local/bin ``` All platforms - non-standard gcc @@ -100,5 +110,5 @@ Please contact the author for a list of recommended parameters for much larger o FUNDING ======= The developmenr of STAR is supported by the National Human Genome Research Institute of -the National Institutes of Health under Award Number R01HG009318. -The content is solely the responsibility of the authors and does not necessarily represent the official views of the National Institutes of Health. \ No newline at end of file +the National Institutes of Health under Award Number R01HG009318. +The content is solely the responsibility of the authors and does not necessarily represent the official views of the National Institutes of Health. diff --git a/RELEASEnotes.md b/RELEASEnotes.md index 59fa8dad..0830afdf 100644 --- a/RELEASEnotes.md +++ b/RELEASEnotes.md @@ -1,3 +1,99 @@ +STAR 2.7.9a --- 2021/05/05 ::: STARsolo updates +===================================================== + +* [**Counting *multi-gene* (multimapping) reads**](#multi-gene-reads) +* STARsolo uses [SIMDe](https://github.com/simd-everywhere/simde) package which support different types of SIMD extensions. For processors that do not support AVX extensions, specify the target SIMD architecture, e.g. +``` +make STAR CXXFLAGS_SIMD=sse +``` + + +STAR 2.7.8a --- 2021/02/20 +=========================== +**Major STARsolo updates and many bug fixes** + +* [**Cell calling (filtering) similar to CellRanger:**](docs/STARsolo.md#emptydrop-like-filtering) + * ```--soloCellFilter EmptyDrops_CR``` option for cell filtering (calling) nearly identical to that of CellRanger 3 and 4 + * ```--runMode soloCellFiltering``` option for cell filtering (calling) of the raw count matrix, without re-mapping +* [**Input from BAM files for STARsolo:**](docs/STARsolo.md#input-reads-from-bam-files) + * Input from unmapped or mapped SAM/BAM for STARsolo, with options ```--soloInputSAMattrBarcodeSeq``` and ```--soloInputSAMattrBarcodeQual``` to specify SAM tags for the barcode read sequence and qualities +* [**Read trimming similar to CellRanger4:**](docs/STARsolo.md#matching-cellranger-4xx-and-5xx-results) + * ```--clipAdapterType CellRanger4``` option for 5' TSO adapter and 3' polyA-tail clipping of the reads to better match CellRanger >= 4.0.0 mapping results +* [**Support for barcodes embedded in mates (such as 10X 5' protocol):**](docs/STARsolo.md#barcode-and-cdna-on-the-same-mate) + * ```--soloBarcodeMate``` to support scRNA-seq protocols in which one of the paired-end mates contains both barcode sequence and cDNA (e.g. 10X 5' protocol) + +STAR 2.7.7a --- 2020/12/28 +========================== +**Major new feature: +STARconsensus: mapping RNA-seq reads to consensus genome.** + +* Provide the VCF file with consensus SNVs and InDels at the genome generation stage with ```--genomeTransformVCF Variants.vcf --genomeTransformType Haploid```. +The alternative alleles in this VCF will be inserted to the reference genome to create a "transformed" genome. +Both the genome sequence and transcript/gene annotations are transformed. + +* At the mapping stage, the reads will be mapped to the transformed (consensus) genome. +The quantification in the transformed annotations can be performed with standard ```--quantMode TranscriptomeSAM and/or GeneCounts``` options. +If desired, alignments (SAM/BAM) and spliced junctions (SJ.out.tab) can be transformed back to the original (reference) coordinates with ```--genomeTransformOutput SAM and/or SJ```. +This is useful if downstream processing relies on reference coordinates. + +STAR 2.7.6a --- 2020/09/19 +========================== +**Major new feature:** +Output multimapping chimeric alignments in BAM format using +``` +--chimMultimapNmax N>1 --chimOutType WithinBAM --outSAMtype BAM Unsorted [and/or] SortedByCoordinate +``` +Many thanks to Sebastian @suhrig who implemented this feature! +More detailed description from Sebastian in PR #802. + +STAR 2.7.5a 2020/06/16 +====================== +**Major new features: +~ support for Plate-based (Smart-seq) scRNA-seq +~ manifest file to list the input reads FASTQ files** + +* Typical STAR command for mapping and quantification of plate-based (Smart-seq) scRNA-seq will look like: +``` + --soloType SmartSeq --readFilesManifest /path/to/manifest.tsv --soloUMIdedup Exact --soloStrand Unstranded +``` +For detailed description, see [Plate-based (Smart-seq) scRNA-seq](docs/STARsolo.md#plate-based-Smart-seq-scRNA-seq) + +* The convenient way to list a large number of reads FASTQ files and their IDs is to create a file manifest and supply it in `--readFilesManifest /path/to/manifest.tsv`. The manifest file should contain 3 tab-separated columns. For paired-end reads: +``` +Read1-file-name \t Read2-file-name \t File-id +``` +For single-end reads, the 2nd column should contain the dash - : +``` +Read1-file-name \t - \t File-id +``` +File-id can be any string without spaces. File-id will be added as ReadGroup tag (*RG:Z:*) for each read in the SAM/BAM output. If File-id starts with *ID:*, it can contain several fields separated by tab, and all the fields will be copied verbatim into SAM *@RG* header line. + + +STAR 2.7.4a 2020/06/01 +====================== +This release fixes multiple bugs and issues. +The biggest issue fixed was a seg-fault for small genome which previously required scaling down `--genomeSAindexNbases`. Such scaling is still recommended but is no longer required. +**This release requires re-generation of the genome indexes** + +STAR 2.7.3a 2019/10/08 +====================== +Major new features in STARsolo +------------------------------ +* **Output enhancements:** + * Summary.csv statistics output for raw and filtered cells useful for quick run quality assessment. + * --soloCellFilter option for basic filtering of the cells, similar to the methods used by CellRanger 2.2.x. +* [**Better compatibility with CellRanger 3.x.x:**](docs/STARsolo.md#matching-cellranger-3xx-results) + * --soloUMIfiltering MultiGeneUMI option introduced in CellRanger 3.x.x for filtering UMI collisions between different genes. + * --soloCBmatchWLtype 1MM_multi_pseudocounts option, introduced in CellRanger 3.x.x, which slightly changes the posterior probability calculation for CB with 1 mismatch. +* [**Velocyto spliced/unspliced/ambiguous quantification:**](docs/STARsolo.md#velocyto-splicedunsplicedambiguous-quantification) + * --soloFeatures Velocyto option to produce Spliced, Unspliced, and Ambiguous counts similar to the [velocyto.py](http://velocyto.org/) tool developed by [LaManno et al](https://doi.org/10.1038/s41586-018-0414-6). This option is under active development and the results may change in the future versions. +* [**Support for complex barcodes, e.g. inDrop:**](docs/STARsolo.md#barcode-geometry) + * Complex barcodes in STARsolo with --soloType CB_UMI_Complex, --soloCBmatchWLtype --soloAdapterSequence, --soloAdapterMismatchesNmax, --soloCBposition,--soloUMIposition +* [**BAM tags:**](#bam-tags) + * CB/UB for corrected CellBarcode/UMI + * GX/GN for gene ID/name +* STARsolo most up-to-date [documentation](docs/STARsolo.md). + STAR 2.7.2a 2019/08/13 ====================== @@ -17,10 +113,10 @@ STAR 2.7.0c 2019/02/05 STARsolo: mapping, demultiplexing and gene quantification for single cell RNA-seq --------------------------------------------------------------------------------- STARsolo is a turnkey solution for analyzing droplet single cell RNA sequencing data (e.g. 10X Genomics Chromium System) built directly into STAR code. -STARsolo inputs the raw FASTQ reads files, and performs the following operations +STARsolo inputs the raw FASTQ reads files, and performs the following operations * error correction and demultiplexing of cell barcodes using user-input whitelist * mapping the reads to the reference genome using the standard STAR spliced read alignment algorithm -* error correction and collapsing (deduplication) of Unique Molecular Identifiers (UMIa) +* error correction and collapsing (deduplication) of Unique Molecular Identifiers (UMIa) * quantification of per-cell gene expression by counting the number of reads per gene STARsolo output is designed to be a drop-in replacement for 10X CellRanger gene quantification output. @@ -29,15 +125,15 @@ At the same time STARsolo is ~10 times faster than the CellRanger. The STAR solo algorithm is turned on with: ``` ---soloType Droplet +--soloType Droplet ``` Presently, the cell barcode whitelist has to be provided with: -``` +``` --soloCBwhitelist /path/to/cell/barcode/whitelist ``` -The 10X Chromium whitelist file can be found inside the CellRanger distribution, +The 10X Chromium whitelist file can be found inside the CellRanger distribution, e.g. [10X-whitelist](https://kb.10xgenomics.com/hc/en-us/articles/115004506263-What-is-a-barcode-whitelist-). Please make sure that the whitelist is compatible with the specific version of the 10X chemistry (V1,V2,V3 etc). @@ -105,20 +201,20 @@ If the overlap is found, STAR will map merge the mates and attempt to map the re If requested, the chimeric detection will be performed on the merged-mate sequence, thus allowing chimeric detection in the overlap region. If the score of this alignment higher than the original one, or if a chimeric alignment is found, STAR will report the merged-mate aligment instead of the original one. In the output, the merged-mate aligment will be converted back to paired-end format. -The developmment of this algorithm was supported by Illumina, Inc. +The developmment of this algorithm was supported by Illumina, Inc. Many thanks to June Snedecor, Xiao Chen, and Felix Schlesinger for their extensive help in developing this feature. **2. Detection of personal variants overlapping alignments.** -Option --varVCFfile /path/to/vcf/file is used to input VCF file with personal variants. Only single nucleotide variants (SNVs) are supported at the moment. +Option --varVCFfile /path/to/vcf/file is used to input VCF file with personal variants. Only single nucleotide variants (SNVs) are supported at the moment. Each variant is expected to have a genotype with two alleles. -To output variants that overlap alignments, vG and vA have to be added to --outSAMattributes list. +To output variants that overlap alignments, vG and vA have to be added to --outSAMattributes list. SAM attribute vG outputs the genomic coordinate of the variant, allowing for identification of the variant. SAM attribute vA outputs which allele is detected in the read: 1 or 2 match one of the genotype alleles, 3 - no match to genotype. **3. WASP filtering of allele specific alignments.** This is re-implementation of the original WASP algorithm by Bryce van de Geijn, Graham McVicker, Yoav Gilad & Jonathan K Pritchard. Please cite the original [WASP paper: Nature Methods 12, 1061–1063 (2015) ](https://www.nature.com/articles/nmeth.3582). -WASP filtering is activated with --waspOutputMode SAMtag, which will add vW tag to the SAM output: +WASP filtering is activated with --waspOutputMode SAMtag, which will add vW tag to the SAM output: vW:i:1 means alignment passed WASP filtering, while all other values mean it did not pass. Many thanks to Bryce van de Geijn for fruitful discussions. @@ -147,17 +243,17 @@ STAR 2.5.0a 2015/11/06 Major new features: ------------------- -1. It is now possible to add extra sequences to the reference genome ont the fly (without re-generating the genome) by specifying -_--genomeFastaFiles /path/to/genome/fasta1 /path/to/genome/fasta2_ at the mapping stage. +1. It is now possible to add extra sequences to the reference genome ont the fly (without re-generating the genome) by specifying +_--genomeFastaFiles /path/to/genome/fasta1 /path/to/genome/fasta2_ at the mapping stage. 2. By default, the order of the multi-mapping alignments for each read is not truly random. -The _--outMultimapperOrder Random_ option outputs multiple alignments for each read in random order, -and also also randomizes the choice of the primary alignment from the highest scoring alignments. -Parameter _--runRNGseed_ can be used to set the random generator seed. -With this option, the ordering of multi-mapping alignments of each read, +The _--outMultimapperOrder Random_ option outputs multiple alignments for each read in random order, +and also also randomizes the choice of the primary alignment from the highest scoring alignments. +Parameter _--runRNGseed_ can be used to set the random generator seed. +With this option, the ordering of multi-mapping alignments of each read, and the choice of the primary alignment will vary from run to run, unless only one thread is used and the seed is kept constant. -3. The --outSAMmultNmax parameter limits the number of output alignments (SAM lines) for multimappers. +3. The --outSAMmultNmax parameter limits the number of output alignments (SAM lines) for multimappers. For instance, _--outSAMmultNmax 1_ will output exactly one SAM line for each mapped read. @@ -173,13 +269,13 @@ The counts coincide with those produced by htseq-count with default parameters. Requires annotations (GTF or GFF with --sjdbGTFfile option) used at the genome generation step, or at the mapping step. Outputs read counts per gene into ReadsPerGene.out.tab file with 4 columns which correspond to different strandedness options: -column 1: gene ID +column 1: gene ID column 2: counts for unstranded RNA-seq column 3: counts for the 1st read strand aligned with RNA (htseq-count option -s yes) column 4: counts for the 2nd read strand aligned with RNA (htseq-count option -s reverse) Select the output according to the strandedness of your data. Note, that if you have stranded data and choose one of the columns 3 or 4, the other column (4 or 3) will give you the count of antisense reads. - + With --quantMode TranscriptomeSAM GeneCounts, and get both the Aligned.toTranscriptome.out.bam and ReadsPerGene.out.tab outputs. @@ -196,7 +292,7 @@ New features: The on the fly genome indices can be saved (for reuse) with "--sjdbInsertSave All", into _STARgenome directory inside the current run directory. Default --sjdbOverhang is now set at 100, and does not have to be specified unless you need to change this value. - The "all-sample" 2-pass method can be simplified using this on the fly junction insertion option: + The "all-sample" 2-pass method can be simplified using this on the fly junction insertion option: (i) run the 1st pass for all samples as usual, with or without annotations (ii) run 2nd pass for all samples, listing SJ.out.tab files from all samples in --sjdbFileChrStartEnd /path/to/sj1.tab /path/to/sj2.tab ... @@ -208,12 +304,12 @@ New features: 3. Included link (submodule) to Brian Haas' STAR-Fusion code for detecting fusion transcript from STAR chimeric output: https://github.com/STAR-Fusion/STAR-Fusion -4. Included Gery Vessere's shared memory implementation for POSIX and SysV. +4. Included Gery Vessere's shared memory implementation for POSIX and SysV. To compile STAR with POSIX shared memory, use `make POSIXSHARED` 5. New option "--chimOutType WithinBAM" to include chimeric alignments together with normal alignments in the main (sorted or unsorted) BAM file(s). Formatting of chimeric alignments follows the latest SAM/BAM specifications. Thanks to Felix Schlesinger for thorough testing of this option. -6. New option "--quantTranscriptomeBan Singleend" allows insertions, deletions ans soft-clips in the transcriptomic alignments, which can be used by some expression quantification software (e.g. eXpress). - +6. New option "--quantTranscriptomeBan Singleend" allows insertions, deletions ans soft-clips in the transcriptomic alignments, which can be used by some expression quantification software (e.g. eXpress). + 7. New option "--alignEndsTypeExtension Extend5pOfRead1" to enforce full extension of the 5p of the read1, while all other ends undergo local alignment and may be soft-clipped. diff --git a/bin/Linux_x86_64/STAR b/bin/Linux_x86_64/STAR index 5db8d1b5..5773f61a 100755 Binary files a/bin/Linux_x86_64/STAR and b/bin/Linux_x86_64/STAR differ diff --git a/bin/Linux_x86_64/STARlong b/bin/Linux_x86_64/STARlong index f64ffb29..774e60bd 100755 Binary files a/bin/Linux_x86_64/STARlong and b/bin/Linux_x86_64/STARlong differ diff --git a/bin/Linux_x86_64_static/STAR b/bin/Linux_x86_64_static/STAR index e58f15cf..dd7f8166 100755 Binary files a/bin/Linux_x86_64_static/STAR and b/bin/Linux_x86_64_static/STAR differ diff --git a/bin/Linux_x86_64_static/STARlong b/bin/Linux_x86_64_static/STARlong index 7c94d0e6..d8758afc 100755 Binary files a/bin/Linux_x86_64_static/STARlong and b/bin/Linux_x86_64_static/STARlong differ diff --git a/bin/MacOSX_x86_64/STAR b/bin/MacOSX_x86_64/STAR old mode 100755 new mode 100644 index 6b584677..46f24a92 Binary files a/bin/MacOSX_x86_64/STAR and b/bin/MacOSX_x86_64/STAR differ diff --git a/bin/MacOSX_x86_64/STARlong b/bin/MacOSX_x86_64/STARlong old mode 100755 new mode 100644 index e044779b..56f8ceec Binary files a/bin/MacOSX_x86_64/STARlong and b/bin/MacOSX_x86_64/STARlong differ diff --git a/doc/STARmanual.pdf b/doc/STARmanual.pdf index 7b94afda..8392aed7 100644 Binary files a/doc/STARmanual.pdf and b/doc/STARmanual.pdf differ diff --git a/docs/STARconsensus.md b/docs/STARconsensus.md new file mode 100644 index 00000000..87ed1e94 --- /dev/null +++ b/docs/STARconsensus.md @@ -0,0 +1,13 @@ +STARconsensus: mapping RNA-seq reads to consensus genome. +========================================================= + +* Introduced in STAR 2.7.7a (2020/12/28) + +* Provide the VCF file with consensus SNVs and InDels at the genome generation stage with ```--genomeTransformVCF Variants.vcf --genomeTransformType Haploid```. +The alternative alleles in this VCF will be inserted to the reference genome to create a "transformed" genome. +Both the genome sequence and transcript/gene annotations are transformed. + +* At the mapping stage, the reads will be mapped to the tranformed (consensus) genome. +The quantification in the transformed annotations can be performed with standard ```--quantMode TranscriptomeSAM and/or GeneCounts``` options. +If desired, alignments (SAM/BAM) and spliced junctions (SJ.out.tab) can be transformed back to the original (reference) coordinates with ```--genomeTransformOutput SAM and/or SJ```. +This is useful if downstream processing relies on reference coordinates. diff --git a/docs/STARsolo.md b/docs/STARsolo.md index 86b248ec..d72e8cc6 100644 --- a/docs/STARsolo.md +++ b/docs/STARsolo.md @@ -1,43 +1,349 @@ -STARsolo: mapping, demultiplexing and gene quantification for single cell RNA-seq ---------------------------------------------------------------------------------- +**STARsolo**: mapping, demultiplexing and quantification for single cell RNA-seq +================================================================================= -First released in STAR 2.7.0a (Jan 23 2019) +Major update in STAR 2.7.9a (2021/05/05) +----------------------------------------- +* [**Counting *multi-gene* (multimapping) reads**](#multi-gene-reads) +Major updates in STAR 2.7.8a (2021/02/20) +----------------------------------------- +* [**Cell calling (filtering) similar to CellRanger:**](#emptydrop-like-filtering) + * ```--soloCellFilter EmptyDrops_CR``` option for cell filtering (calling) nearly identical to that of CellRanger 3 and 4 + * ```--runMode soloCellFiltering``` option for cell filtering (calling) of the raw count matrix, without re-mapping +* [**Input from BAM files for STARsolo:**](#input-reads-from-bam-files) + * Input from unmapped or mapped SAM/BAM for STARsolo, with options ```--soloInputSAMattrBarcodeSeq``` and ```--soloInputSAMattrBarcodeQual``` to specify SAM tags for the barcode read sequence and qualities +* [**Read trimming similar to CellRanger4:**](#matching-cellranger-4xx-and-5xx-results) + * ```--clipAdapterType CellRanger4``` option for 5' TSO adapter and 3' polyA-tail clipping of the reads to better match CellRanger >= 4.0.0 mapping results +* [**Support for barcodes embedded in mates (such as 10X 5' protocol):**](#barcode-and-cdna-on-the-same-mate) + * ```--soloBarcodeMate``` to support scRNA-seq protocols in which one of the paired-end mates contains both barcode sequence and cDNA (e.g. 10X 5' protocol) + + +STARsolo +------------- STARsolo is a turnkey solution for analyzing droplet single cell RNA sequencing data (e.g. 10X Genomics Chromium System) built directly into STAR code. -STARsolo inputs the raw FASTQ reads files, and performs the following operations +STARsolo inputs the raw FASTQ reads files, and performs the following operations * error correction and demultiplexing of cell barcodes using user-input whitelist * mapping the reads to the reference genome using the standard STAR spliced read alignment algorithm -* error correction and collapsing (deduplication) of Unique Molecular Identifiers (UMIa) +* error correction and collapsing (deduplication) of Unique Molecular Identifiers (UMIa) * quantification of per-cell gene expression by counting the number of reads per gene +* quantification of other transcriptomic features: splice junctions; pre-mRNA; spliced/unspliced reads similar to Velocyto STARsolo output is designed to be a drop-in replacement for 10X CellRanger gene quantification output. It follows CellRanger logic for cell barcode whitelisting and UMI deduplication, and produces nearly identical gene counts in the same format. At the same time STARsolo is ~10 times faster than the CellRanger. -The STAR solo algorithm is turned on with: +Running STARsolo for 10X Chromium scRNA-seq data +------------------------------------- +* STARsolo is run the same way as normal STAR run, with addition of several STARsolo parameters: + ``` + /path/to/STAR --genomeDir /path/to/genome/dir/ --readFilesIn ... [...other parameters...] --soloType ... --soloCBwhitelist ... + ``` + The genome index is the same as for normal STAR runs.
+ The parameters required to run STARsolo on 10X Chromium data are described below: + +* The STAR solo algorithm is turned on with: + ``` + --soloType Droplet + ``` + or, since 2.7.3a, with more descriptive: + ``` + --soloType CB_UMI_Simple + ``` + +* The CellBarcode whitelist has to be provided with: + + ``` + --soloCBwhitelist /path/to/cell/barcode/whitelist + ``` + The 10X Chromium [whitelist](https://kb.10xgenomics.com/hc/en-us/articles/115004506263-What-is-a-barcode-whitelist-) files can be found or inside the CellRanger distribution or on [GitHub/10XGenomics](https://github.com/10XGenomics/cellranger/tree/master/lib/python/cellranger/barcodes). +Please make sure that the whitelist is compatible with the specific version of the 10X chemistry: V2 or V3. For instance, in CellRanger 3.1.0, the *V2 whitelist* is: + ``` + cellranger-cs/3.1.0/lib/python/cellranger/barcodes/737K-august-2016.txt + + https://github.com/10XGenomics/cellranger/raw/master/lib/python/cellranger/barcodes/737K-august-2016.txt + ``` + and *V3 whitelist* (gunzip it for STARsolo): + ``` + cellranger-cs/3.1.0/lib/python/cellranger/barcodes/3M-february-2018.txt.gz + + https://github.com/10XGenomics/cellranger/raw/master/lib/python/cellranger/barcodes/3M-february-2018.txt.gz + ``` +* The default barcode lengths (CB=16b, UMI=10b) work for 10X Chromium V2. For V3, specify: + ``` + --soloUMIlen 12 + ``` + +* Importantly, in the --readFilesIn option, the 1st file has to be cDNA read, and the 2nd file has to be the barcode (cell+UMI) read, i.e. + ``` + --readFilesIn cDNAfragmentSequence.fastq.gz CellBarcodeUMIsequence.fastq.gz + ``` + For instance, standard 10X runs have cDNA as Read2 and barcode as Read1: + ``` + --readFilesIn Read2.fastq.gz Read1.fastq.gz + ``` + For multiple lanes, use commas separated lists for Read2 and Read1: + ``` + --readFilesIn Read2_Lane1.fastq.gz,Read2_Lane2.fastq.gz,Read2_Lane3.fastq.gz Read1_Lane1.fastq.gz,Read1_Lane2.fastq.gz,Read1_Lane3.fastq.gz + ``` +---------------------------------------- +How to make STARsolo _raw_ gene counts (almost) identical to CellRanger's +---------------------------------------------------------------------- +* CellRanger uses its own "filtered" version of annotations (GTF file) which is a subset of ENSEMBL annotations, with several gene biotypes removed (mostly small non-coding RNA). Annotations affect the counts, and to match CellRanger counts CellRanger annotations have to be used. + +* 10X provides several versions of the CellRanger annotations:
+ [https://support.10xgenomics.com/single-cell-gene-expression/software/downloads/latest ](https://support.10xgenomics.com/single-cell-gene-expression/software/downloads/latest)
+ For the best match, the annotations in CellRanger run and STARsolo run should be exactly the same. + +* The FASTA and GTF files, for one of the older releases: + ``` + refdata-cellranger-GRCh38-3.0.0/genes/genes.gtf + refdata-cellranger-GRCh38-3.0.0/fasta/genome.fa + ``` + or, for the latest release: + ``` + refdata-gex-GRCh38-2020-A/genes/genes.gtf + refdata-gex-GRCh38-2020-A/fasta/genome.fa + ``` + have to be used in STAR genome index generation step before mapping: + ``` + STAR --runMode genomeGenerate --runThreadN ... --genomeDir ./ --genomeFastaFiles /path/to/genome.fa --sjdbGTFfile /path/to/genes.gtf + ``` + +* If you want to use your own GTF (e.g. newer version of ENSEMBL or GENCODE), you can generate the "filtered" GTF file using 10X's mkref tool:
+ [https://support.10xgenomics.com/single-cell-gene-expression/software/pipelines/latest/advanced/references](https://support.10xgenomics.com/single-cell-gene-expression/software/pipelines/latest/advanced/references) + +* To make the agreement between STARsolo and CellRanger even more perfect, you can add + ``` + --genomeSAsparseD 3 + ``` + to the genome generation options, which is used by CellRanger to generate STAR genomes. It will generate sparse suffixs array which has an additional benefit of fitting into 16GB of RAM. However, it also results in 30-50% reduction of speed. + +* The considerations above are for *raw* counts, i.e. when cell filtering (calling) is not performed. To get *filtered* cells, refer to [Cell filtering (calling)](#Cell-filtering-calling) section. + +#### Matching CellRanger 3.x.x results +* By default, cell barcode and UMI collapsing parameters are designed to give the best agreement with CellRanger 2.x.x. CellRanger 3.x.x introduced some minor changes to this algorithm. To get the best agreement between STARsolo and CellRanger 3.x.x, add these parameters: + ``` + --soloCBmatchWLtype 1MM_multi_Nbase_pseudocounts --soloUMIfiltering MultiGeneUMI_CR --soloUMIdedup 1MM_CR + ``` + +#### Matching CellRanger 4.x.x and 5.x.x results +* Starting from CellRanger 4.0, the TSO adapter sequence is clipped from the 5' of the cDNA read, and polyA-tail is trimmed from the 3'. For the best mathch to CellRanger >= 4.0, use these parameters: + ``` + --clipAdapterType CellRanger4 --outFilterScoreMin 30 + --soloCBmatchWLtype 1MM_multi_Nbase_pseudocounts --soloUMIfiltering MultiGeneUMI_CR --soloUMIdedup 1MM_CR + ``` +The adapter clipping utilizes vectorized Smith-Waterman algorithm from Opal package by Martin Šošić: https://github.com/Martinsos/opal + +----------------- +Barcode geometry +------------------- +#### Simple barcodes +Simple barcode lengths and start positions on barcode reads are described with +``` +--soloCBstart, --soloCBlen, --soloUMIstart, --soloUMIlen +``` +which works with +``` +--soloType CB_UMI_Simple (a.k.a Droplet) +``` +#### Barcode and cDNA on the same mate +By default, it is assumed that the barcode is located on one of the mates of paired-end read, while cDNA is on the other mate. However, in some scRNA-seq protocols the barcode and cDNA sequences are located on the same mate. In this case, we can specify the mate on which the barcode is located (1 or 2) with ```--soloBarcodeMate```. Also, the barcode/adapter sequences have to be clipped (leaving only cDNA) with ```--clip5pNbases``` or ```--clip3pNbases```. + +For instance, for the **10X 5' protocol**, the 1st mate contains the barcode at the 5', with 16b CB, 10b UMI and 13b adapter (39b total). If the 1st mate is sequenced longer than 39b, the remaining bases are cDNA that can be mapped together with the 2nd mate (which contains only cDNA): ``` ---soloType Droplet +--soloBarcodeMate 1 --clip5pNbases 39 0 +--soloType CB_UMI_Simple --soloCBstart 1 --soloCBlen 16 --soloUMIstart 17 --soloUMIlen 10 +--readFilesIn read1.fq read2.fq ``` -Presently, the cell barcode whitelist has to be provided with: -``` ---soloCBwhitelist /path/to/cell/barcode/whitelist +#### Complex barcodes +More complex barcodes are activated with ```--soloType CB_UMI_Complex``` and are described with the following parameters ``` +soloCBposition - +strings(s) position of Cell Barcode(s) on the barcode read. + Presently only works with --soloType CB_UMI_Complex, and barcodes are assumed to be on Read2. + Format for each barcode: startAnchor_startDistance_endAnchor_endDistance + start(end)Anchor defines the anchor base for the CB: 0: read start; 1: read end; 2: adapter start; 3: adapter end + start(end)Distance is the distance from the CB start(end) to the Anchor base + String for different barcodes are separated by space. + Example: inDrop (Zilionis et al, Nat. Protocols, 2017): + --soloCBposition 0_0_2_-1 3_1_3_8 -The 10X Chromium whitelist file can be found inside the CellRanger distribution, -e.g. [10X-whitelist](https://kb.10xgenomics.com/hc/en-us/articles/115004506263-What-is-a-barcode-whitelist-). -Please make sure that the whitelist is compatible with the specific version of the 10X chemistry (V1,V2,V3 etc). +soloUMIposition - +string position of the UMI on the barcode read, same as soloCBposition + Example: inDrop (Zilionis et al, Nat. Protocols, 2017): + --soloUMIposition 3_9_3_14 -Importantly, in the --readFilesIn option, the 1st file has to be cDNA read, and the 2nd file has to be the barcode (cell+UMI) read, i.e. +soloAdapterSequence - +string: adapter sequence to anchor barcodes. + +soloAdapterMismatchesNmax 1 +int>0: maximum number of mismatches allowed in adapter sequence +``` + + + +-------------------------------------- +Cell filtering (calling) +-------------------------------------- +In addition to raw, unfiltered output of gene/cell counts, STARsolo performs cell filtering (a.k.a. cell calling), which aims to select a subset of cells that are likely to be "real" cells as opposed to empty droplets (containing ambient RNA). +Two types of filtering are presently implemented: simple (knee-like) and advanced EmptyDrop-like. The selected filtering is also used to produce summary statistics for filtered cells in the Summary.csv file, which is similar to CellRanger's summary and is useful for Quality Control. + +#### Knee filtering +Knee filtering is similar to the method used by CellRanger 2.2.x. This is turned on by default and is controlled by: ``` ---readFilesIn cDNAfragmentSequence.fastq.gz CellBarcodeUMIsequence.fastq.gz +--soloCellFilter CellRanger2.2 ``` +You can also add three numbers for this option (default values are given in parenthesis): the number of expected cells (3000), robust maximum percentile for UMI count (0.99), maximum to minimum ratio for UMI count (10). -Important: the genome index has to be re-generated with the latest 2.7.0x release. +#### EmptyDrop-like filtering +CellRanger 3.0.0 use advanced filtering based on the EmptyDrop algorithm developed by [Lun et al](https://doi.org/10.1186/s13059-019-1662-y). This algorithm calls extra cells compared to the knee filtering, allowing for cells that have relatively fewer UMIs but are transcriptionally different from the ambient RNA. In STARsolo, this filtering can be activated by: +``` +--soloCellFilter EmptyDrops_CR +``` +It can be followed by 10 numeric parameters: nExpectedCells (3000), maxPercentile (0.99), maxMinRatio (10), indMin (45000), indMax (90000), umiMin (500), umiMinFracMedian (0.01), candMaxN (20000), FDR (0.01), simN (10000). + +#### Cell filtering of previously generated raw matrix +It is possible to run only the filtering algorithm (without the need to re-map) inputting the previously generated **raw** matrix: +``` +STAR --runMode soloCellFiltering /path/to/count/dir/raw/ /path/to/output/prefix --soloCellFilter EmptyDrops_CR +``` +The */path/to/count/dir/raw/* directory should contain the **"raw"** *barcodes.tsv*, *features.tsv*, and *matrix.mtx* files generated in a previos STARsolo run. +The output will contain the filtered files. -Other parameters that control STARsolo output are listed below. Note that default parameters are compatible with 10X Chromium V2 protocol. +-------------------------------------------------- +Quantification of different transcriptomic features +--------------------------------------------------- +* In addition to the gene counts (deafult), STARsolo can calculate counts for other transcriptomic features: + * pre-mRNA counts, useful for single-nucleus RNA-seq. This counts all read that overlap gene loci, i.e. included both exonic and intronic reads: + ``` + --soloFeatures GeneFull + ``` + * Counts for annotated and novel splice junctions: + ``` + --soloFeatures SJ + ``` + * #### Velocyto spliced/unspliced/ambiguous quantification + This option will calculate Spliced, Unspliced, and Ambiguous counts per cell per gene similar to the [velocyto.py](http://velocyto.org/) tool developed by [LaManno et al](https://doi.org/10.1038/s41586-018-0414-6). This option is under active development and the results may change in the future versions. + ``` + --soloFeatures Gene Velocyto + ``` + Note that Velocyto quantification requires Gene features + * All the features can be conveniently quantified in one run: + ``` + --soloFeatures Gene GeneFull SJ Velocyto + ``` +------------------------------------------------------ +Multi-gene reads +------------------------------------------------------ +Multi-gene reads are concordant with (i.e. align equally well to) transcripts of two or more genes. One class of multi-gene read are those that map uniquely to a genomic region where two or more genes overlap. Another class are those reads that map to multiple loci in the genome, with each locus annotated to a different gene. + +Including multi-gene reads allows for more accurate gene quantification and, more importantly, enables detection of gene expression from certain classes of genes that are supported only by multi-gene reads, such as overlapping genes and highly similar paralog families. + +The multi-gene read recovery options are specified with ```--soloMultiMappers```. Several algorithms are implemented: + +``` +--soloMultiMappers Uniform +``` +uniformly distributes the multi-gene UMIs to all genes in its gene set. Each gene gets a fractional count of 1/N_genes, where N_genes is the number of genes in the set. This is the simplest possible option, and it offers higher sensitivity for gene detection at the expense of lower precision. + +``` +--soloMultiMappers PropUnique +``` + distributes the multi-gene UMIs proportionally to the number of unique UMIs per gene. UMIs that map to genes that are not supported by unique UMIs are distributed uniformly. + +``` +--soloMultiMappers EM ``` +uses Maximum Likelihood Estimation (MLE) to distribute multi-gene UMIs among their genes, taking into account other UMIs (both unique- and multi-gene) from the same cell (i.e. with the same CB). Expectation-Maximization (EM) algorithm is used to find the gene expression values that maximize the likelihood function. Recovering multi-gene reads via MLE-EM model was previously used to quantify transposable elements in bulk RNA-seq {[TEtranscripts](https://doi.org/10.1093/bioinformatics/btv422)} and in scRNA-seq {[Alevin](https://doi.org/10.1186/s13059-019-1670-y); [Kallisto-bustools](http://www.nature.com/articles/s41587-021-00870-2)}. + +``` +--soloMultiMappers Rescue +``` +distributes multi-gene UMIs to their gene set proportionally to the sum of the number of unique-gene UMIs and uniformly distributed multi-gene UMIs in each gene [Mortazavi et al](https://www.nature.com/articles/nmeth.1226). It can be thought of as the first step of the EM algorithm. + +Any combination of these options can be specified and different multi-gene falvors will be output into different files. The unique-gene UMI counts are output into the *matrix.mtx* file in the *raw/Gene* directory, while the sum of unique+multi-gene UMI counts will be output into *UniqueAndMult-EM.mtx, UniqueAndMult-PropUnique.mtx, UniqueAndMult-Rescue.mtx, UniqueAndMult-Uniform.mtx* files. + +-------------------------------------- +BAM tags +-------------------------------------- +* To output BAM tags into SAM/BAM file, add them to the list of standard tags in + ``` + --outSAMattributes NH HI nM AS CR UR CB UB GX GN sS sQ sM + ``` + Any combinations of tags can be used. +* CR/UR: **raw (uncorrected)** CellBarcode/UMI +* CY/UY: quality score for CellBarcode/UMI +* GX/GN: for gene ID/names +* sS/sQ: for sequence/quality combined CellBarcode and UMI; sM for barcode match status. +* CB/UB: **corrected** CellBarcode/UMI. Note, that these tags require sorted BAM output, i.e. we need to add the following option: + ``` + --outSAMtype BAM SortedByCoordinate + ``` + +--------------------------------------- +Input reads from BAM files. +------------------------------- +The read sequences and barcodes can be input from SAM (or BAM) files, both unmapped (uBAM) and previously mapped (e.g. Cellranger's BAM): +``` +--readFilesIn input.bam --readFilesType SAM SE +``` +In case of BAM files, use ```samtools view``` command to convert to BAM: +``` +--readFilesCommand samtools view -F 0x100 +``` +The file should contain one line for each read. For previously mapped file it can be achieved by filtering out non-primary alignments as shown above. Note that unmapped reads have to be included in the file to be remapped. +We need to specify which SAM attributes correspond to seqeunces/qualities of cell barcodes (CR/CY) and UMIs (UR/UY): +``` +--soloInputSAMattrBarcodeSeq CR UR --soloInputSAMattrBarcodeQual CY UY +``` +If you wish to omit some, All or None of the SAM attributes in the output BAM file (if you requested one), use ```--readFilesSAMattrKeep``` option. For previously mapped files, ```--readFilesSAMattrKeep None``` is often the best option to avoid duplicated SAM attributes in the BAM output. + +If you request coordinate-sorted BAM output, and use a coordinate-sorted mapped BAM input (such as CellRanger's possorted BAM), it may result in slow sorting and require large amountss of RAM. In this case, it is recommended to shuffle the alignments before mapping with ```samtools bamshuf``` command. + + +-------------------------------- +Different scRNA-seq technologies +-------------------------------- +### Plate-based (Smart-seq) scRNA-seq +Plate-based (Smart-seq) scRNA-seq technologies produce separate FASTQ files for each cell. Cell barcodes are not incorporated in the read sequences, and there are no UMIs. Typical STAR command for mapping and quantification of these file will look like: +``` +--soloType SmartSeq --readFilesManifest /path/to/manifest.tsv --soloUMIdedup Exact --soloStrand Unstranded +``` + +* STARsolo `--soloType SmartSeq` option produces cell/gene (and other [features](#quantification-of-different-transcriptomic-features)) +count matrices, using rules similar to the droplet-based technologies. The differnces are (i) individual cells correspond to different FASTQ files,there are no Cell Barcode sequences, and "Cell IDs" have to be provided as input (ii) there are no UMI sequences, but reads can be deduplicated if they have identical start/end coordinates. + +* The convenient way to list all the FASTQ files and Cell IDs is to create a file manifest and supply it in `--readFilesManifest /path/to/manifest.tsv`. The manifest file should contain 3 tab-separated columns. For paired-end reads: +``` +Read1-file-name \t Read2-file-name \t Cell-id +``` +For single-end reads, the 2nd column should contain the dash - : +``` +Read1-file-name \t - \t Cell-id +``` +Cell-id can be any string without spaces. Cell-id will be added as ReadGroup tag (*RG:Z:*) for each read in the SAM/BAM output. If Cell-id starts with *ID:*, it can contain several fields separated by tab, and all the fields will be copied verbatim into SAM *@RG* header line. +* Deduplication based on read start/end coordinates can be done with `--soloUMIdedup Exact` option. To avoid deduplication (e.g. for single-end reads) use `--soloUMIdedup NoDedup`. Both deduplication options can be used together `--soloUMIdedup Exact NoDedup` and will produce two *.mtx* matrices. +* Common Smart-seq protocols are unstranded and thus will require `--soloStrand Unstranded` option. If your protocol is stranded, you can can choose the proper `--soloStrand Forward` (default) or `--soloStrand Reverse` options. + +------------------------------------------------------------- +------------------------------------------------------ +-------------------------------------------------- +All parameters that control STARsolo output are listed again below with defaults and short descriptions: +--------------------------------------- +``` +soloType None + string(s): type of single-cell RNA-seq + CB_UMI_Simple ... (a.k.a. Droplet) one UMI and one Cell Barcode of fixed length in read2, e.g. Drop-seq and 10X Chromium. + CB_UMI_Complex ... one UMI of fixed length, but multiple Cell Barcodes of varying length, as well as adapters sequences are allowed in read2 only, e.g. inDrop. + CB_samTagOut ... output Cell Barcode as CR and/or CB SAm tag. No UMI counting. --readFilesIn cDNA_read1 [cDNA_read2 if paired-end] CellBarcode_read . Requires --outSAMtype BAM Unsorted [and/or SortedByCoordinate] + SmartSeq ... Smart-seq: each cell in a separate FASTQ (paired- or single-end), barcodes are corresponding read-groups, no UMI sequences, alignments deduplicated according to alignment start and end (after extending soft-clipped bases) + +soloCBwhitelist - + string(s): file(s) with whitelist(s) of cell barcodes. Only --soloType CB_UMI_Complex allows more than one whitelist file. + None ... no whitelist: all cell barcodes are allowed + soloCBstart 1 int>0: cell barcode start base @@ -50,6 +356,58 @@ soloUMIstart 17 soloUMIlen 10 int>0: UMI length +soloBarcodeReadLength 1 + int: length of the barcode read + 1 ... equal to sum of soloCBlen+soloUMIlen + 0 ... not defined, do not check + +soloBarcodeMate 0 + int: identifies which read mate contains the barcode (CB+UMI) sequence + 0 ... barcode sequence is on separate read, which should always be the last file in the --readFilesIn listed + 1 ... barcode sequence is a part of mate 1 + 2 ... barcode sequence is a part of mate 2 + +soloCBposition - + strings(s) position of Cell Barcode(s) on the barcode read. + Presently only works with --soloType CB_UMI_Complex, and barcodes are assumed to be on Read2. + Format for each barcode: startAnchor_startPosition_endAnchor_endPosition + start(end)Anchor defines the Anchor Base for the CB: 0: read start; 1: read end; 2: adapter start; 3: adapter end + start(end)Position is the 0-based position with of the CB start(end) with respect to the Anchor Base + String for different barcodes are separated by space. + Example: inDrop (Zilionis et al, Nat. Protocols, 2017): + --soloCBposition 0_0_2_-1 3_1_3_8 + +soloUMIposition - + string position of the UMI on the barcode read, same as soloCBposition + Example: inDrop (Zilionis et al, Nat. Protocols, 2017): + --soloCBposition 3_9_3_14 + +soloAdapterSequence - + string: adapter sequence to anchor barcodes. + +soloAdapterMismatchesNmax 1 + int>0: maximum number of mismatches allowed in adapter sequence. + +soloCBmatchWLtype 1MM_multi + string: matching the Cell Barcodes to the WhiteList + Exact ... only exact matches allowed + 1MM ... only one match in whitelist with 1 mismatched base allowed. Allowed CBs have to have at least one read with exact match. + 1MM_multi ... multiple matches in whitelist with 1 mismatched base allowed, posterior probability calculation is used choose one of the matches. + Allowed CBs have to have at least one read with exact match. This option matches best with CellRanger 2.2.0 + 1MM_multi_pseudocounts ... same as 1MM_Multi, but pseudocounts of 1 are added to all whitelist barcodes. + 1MM_multi_Nbase_pseudocounts ... same as 1MM_multi_pseudocounts, multimatching to WL is allowed for CBs with N-bases. This option matches best with CellRanger >= 3.0.0 + + +soloInputSAMattrBarcodeSeq - + string(s): when inputting reads from a SAM file (--readsFileType SAM SE/PE), these SAM attributes mark the barcode sequence (in proper order). + For instance, for 10X CellRanger or STARsolo BAMs, use --soloInputSAMattrBarcodeSeq CR UR . + This parameter is required when running STARsolo with input from SAM. + +soloInputSAMattrBarcodeQual - + string(s): when inputting reads from a SAM file (--readsFileType SAM SE/PE), these SAM attributes mark the barcode qualities (in proper order). + For instance, for 10X CellRanger or STARsolo BAMs, use --soloInputSAMattrBarcodeQual CY UY . + If this parameter is '-' (default), the quality 'H' will be assigned to all bases. + soloStrand Forward string: strandedness of the solo libraries: Unstranded ... no strand information @@ -57,21 +415,42 @@ soloStrand Forward Reverse ... read strand opposite to the original RNA molecule soloFeatures Gene - string(s) genomic features for which the UMI counts per Cell Barcode are collected + string(s): genomic features for which the UMI counts per Cell Barcode are collected Gene ... genes: reads match the gene transcript SJ ... splice junctions: reported in SJ.out.tab + GeneFull ... full genes: count all reads overlapping genes' exons and introns soloUMIdedup 1MM_All - string(s) type of UMI deduplication (collapsing) algorithm - 1MM_All ... all UMIs with 1 mismatch distance to each other are collapsed (i.e. counted once) - 1MM_Directional ... follows the "directional" method from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017). - 1MM_NotCollapsed ... UMIs with 1 mismatch distance to others are not collapsed (i.e. all counted) - -soloOutFileNames Solo.out/ genes.tsv barcodes.tsv matrix.mtx matrixSJ.mtx - string(s) file names for STARsolo output - 1st word ... file name prefix - 2nd word ... barcode sequences - 3rd word ... gene IDs and names - 4th word ... cell/gene counts matrix - 5th word ... cell/splice junction counts matrix + string(s): type of UMI deduplication (collapsing) algorithm + 1MM_All ... all UMIs with 1 mismatch distance to each other are collapsed (i.e. counted once). + 1MM_Directional_UMItools ... follows the "directional" method from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017). + 1MM_Directional ... same as 1MM_Directional_UMItools, but with more stringent criteria for duplicate UMIs + Exact ... only exactly matching UMIs are collapsed. + NoDedup ... no deduplication of UMIs, count all reads. + 1MM_CR ... CellRanger2-4 algorithm for 1MM UMI collapsing. + +soloUMIfiltering - + string(s) type of UMI filtering + - ... basic filtering: remove UMIs with N and homopolymers (similar to CellRanger 2.2.0). + MultiGeneUMI ... basic + remove lower-count UMIs that map to more than one gene. + MultiGeneUMI_CR ... basic + remove lower-count UMIs that map to more than one gene, matching CellRanger > 3.0.0 . + Only works with --soloUMIdedup 1MM_CR + +soloOutFileNames Solo.out/ features.tsv barcodes.tsv matrix.mtx + string(s) file names for STARsolo output: + file_name_prefix gene_names barcode_sequences cell_feature_count_matrix + +soloCellFilter CellRanger2.2 3000 0.99 10 + string(s): cell filtering type and parameters + None ... do not output filtered cells + TopCells ... only report top cells by UMI count, followed by the exact number of cells + CellRanger2.2 ... simple filtering of CellRanger 2.2. + Can be followed by numbers: number of expected cells, robust maximum percentile for UMI count, maximum to minimum ratio for UMI count + The harcoded values are from CellRanger: nExpectedCells=3000; maxPercentile=0.99; maxMinRatio=10 + EmptyDrops_CR ... EmptyDrops filtering in CellRanger flavor. Please cite the original EmptyDrops paper: A.T.L Lun et al, Genome Biology, 20, 63 (2019): https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1662-y + Can be followed by 10 numeric parameters: nExpectedCells maxPercentile maxMinRatio indMin indMax umiMin umiMinFracMedian candMaxN FDR simN + The harcoded values are from CellRanger: 3000 0.99 10 45000 90000 500 0.01 20000 0.01 10000 + +soloOutFormatFeaturesGeneField3 "Gene Expression" + string(s): field 3 in the Gene features.tsv file. If "-", then no 3rd field is output. ``` diff --git a/extras/doc-latex/STARmanual.tex b/extras/doc-latex/STARmanual.tex index d33ea8bf..84aa7a96 100644 --- a/extras/doc-latex/STARmanual.tex +++ b/extras/doc-latex/STARmanual.tex @@ -8,6 +8,7 @@ \usepackage{changepage} \usepackage[top=1in, bottom=1in, left=0.7in, right=0.7in]{geometry} \usepackage{enumitem} +\usepackage{tocloft} \begin{document} \hypersetup{ @@ -25,7 +26,7 @@ \newcommand{\optvr}[1]{\sloppy\textit{\texttt{#1}}} \newcommand{\code}[1]{\sloppy\texttt{#1}} - + \newcommand{\codelines}[1]{\begin{adjustwidth}{0.5in}{0in} \raggedright\texttt{#1} \end{adjustwidth}} @@ -34,10 +35,16 @@ \newcommand{\sechyperref}[1]{\hyperref[#1]{Section \ref{#1}. \nameref{#1}}} -\title{STAR manual 2.7.2a} +\title{STAR manual 2.7.9a} \author{Alexander Dobin\\ dobin@cshl.edu} \maketitle + +%\setlength{\cftsubsecindent}{8em} % to control spacing between number and title in the ToC +\makeatletter +\renewcommand*\l@subsection{\@dottedtocline{2}{1.8em}{2.7 em}} +\renewcommand*\l@subsubsection{\@dottedtocline{2}{4.5em}{2.7 em}} +\makeatother \tableofcontents \newpage @@ -46,7 +53,7 @@ \section{Getting started.} \subsection{Installation.} -STAR source code and binaries can be downloaded from GitHub: named releases from \url{https://github.com/alexdobin/STAR/releases}, or the master branch from \url{https://github.com/alexdobin/STAR}. The pre-compiled STAR executables are located \code{bin/} subdirectory. The \code{static} executables are the easisest to use, as they are statically compiled and are not dependents on external libraries. +STAR source code and binaries can be downloaded from GitHub: named releases from \url{https://github.com/alexdobin/STAR/releases}, or the master branch from \url{https://github.com/alexdobin/STAR}. The pre-compiled STAR executables are located \code{bin/} subdirectory. The \code{static} executables are the easisest to use, as they are statically compiled and are not dependents on external libraries. To compile STAR from sources run \code{make} in the source directory for a Linux-like environment, or run \code{make STARforMac} for Mac OS X. This will produce the executable \code{'STAR'} inside the source directory. @@ -65,7 +72,7 @@ \subsubsection{Installation - in depth and troubleshooting.} \$ sudo yum install gcc-c++\\ \$ sudo yum install glibc-static } - + \paragraph{SUSE.}\hfill \codelines {\$ sudo zypper update\\ \$ sudo zypper in gcc gcc-c++ @@ -121,7 +128,7 @@ \subsection{Basic options.} \opt{sjdbOverhang} specifies the length of the genomic sequence around the annotated junction to be used in constructing the splice junctions database. Ideally, this length should be equal to the \optvr{ReadLength-1}, where \optvr{ReadLength} is the length of the reads. For instance, for Illumina 2x100b paired-end reads, the ideal value is 100-1=99. In case of reads of varying length, the ideal value is \optvr{max(ReadLength)-1}. \textbf{In most cases, the default value of 100 will work as well as the ideal value.} \end{itemize} -Genome files comprise binary genome sequence, suffix arrays, text chromosome names/lengths, splice junctions coordinates, and transcripts/genes information. Most of these files use internal STAR format and are not intended to be utilized by the end user. It is strongly \textbf{not recommended} to change any of these file with one exception: you can rename the chromosome names in the chrName.txt keeping the order of the chromosomes in the file: the names from this file will be used in all output files (e.g. SAM/BAM). +Genome files comprise binary genome sequence, suffix arrays, text chromosome names/lengths, splice junctions coordinates, and transcripts/genes information. Most of these files use internal STAR format and are not intended to be utilized by the end user. It is strongly \textbf{not recommended} to change any of these files with one exception: you can rename the chromosome names in the chrName.txt while keeping the order of the chromosomes in this file: the chromosome names from this file will be used in all output files (e.g. SAM/BAM). \subsection{Advanced options.} \subsubsection{Which chromosomes/scaffolds/patches to include?} @@ -131,8 +138,8 @@ \subsubsection{Which chromosomes/scaffolds/patches to include?} \begin{itemize} \item \textbf{ENSEMBL:} files marked with .dna.primary.assembly, such as: \url{ftp://ftp.ensembl.org/pub/release-77/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz} -\item \textbf{GENCODE:} files marked with PRI (primary). Strongly recommended for mouse and human: \url{http://www.gencodegenes.org/}. -\end{itemize} +\item \textbf{GENCODE:} files marked with PRI (primary). Strongly recommended for mouse and human: \url{http://www.gencodegenes.org/}. +\end{itemize} \subsubsection{Which annotations to use?} The use of the most comprehensive annotations for a given species is strongly recommended. Very importantly, chromosome names in the annotations GTF file have to match chromosome names in the FASTA genome sequence files. For example, one can use ENSEMBL FASTA files with ENSEMBL GTF files, and UCSC FASTA files with UCSC FASTA files. However, since UCSC uses \code{chr1, chr2, ...} naming convention, and ENSEMBL uses \code{1, 2, ...} naming, the ENSEMBL and UCSC FASTA and GTF files cannot be mixed together, unless chromosomes are renamed to match between the FASTA anf GTF files. @@ -168,7 +175,7 @@ \subsection{Basic options.} \opt{genomeDir} specifies path to the genome directory where genome indices where generated (see \sechyperref{Generating_genome_indexes}). \item[] -\opt{readFilesIn} name(s) (with path) of the files containing the sequences to be mapped (e.g. RNA-seq FASTQ files). If using Illumina paired-end reads, the \optvr{read1} and \optvr{read2} files have to be supplied. STAR can process both FASTA and FASTQ files. Multi-line (i.e. sequence split in multiple lines) FASTA (but not FASTQ) files are supported. +\opt{readFilesIn} name(s) (with path) of the files containing the sequences to be mapped (e.g. RNA-seq FASTQ files). If using Illumina paired-end reads, the \optvr{read1} and \optvr{read2} files have to be supplied. STAR can process both FASTA and FASTQ files. Multi-line (i.e. sequence split in multiple lines) FASTA (but not FASTQ) files are supported. If the read files are compressed, use the \opt{readFilesCommand} \optvr{UncompressionCommand} option, where \optvr{UncompressionCommand} is the un-compression command that takes the file name as input parameter, and sends the uncompressed output to stdout. For example, for gzipped files (*.gz) use \code{\opt{readFilesCommand} \optv{zcat}} @@ -177,16 +184,42 @@ \subsection{Basic options.} For bzip2-compressed files, use \code{\opt{readFilesCommand} \optv{bunzip2 -c}}. -Multiple samples can be mapped in one job. For single-end reads use a comma separated list (no spaces around commas), e.g. -\opt{readFilesIn} \optv{sample1.fq,sample2.fq,sample3.fq}. For paired-end reads, use comma separated list for read1 /space/ comma separated list for read2, e.g.: \opt{readFilesIn} \optv{sample1read1.fq,sample2read1.fq,sample3read1.fq sample1read2.fq,sample2read2.fq,sample3read2.fq}. - \end{itemize} +\subsection{Mapping multiple files in one run.} +Multiple samples can be mapped in one run with a single output. This is equivalent to concatenating the read files before mapping, except that distinct read groups can be used in \opt{outSAMattrRGline} command to keep track of reads from different files. For single-end reads use a comma separated list (no spaces around commas), e.g.: + +\opt{readFilesIn} \optv{sample1.fq,sample2.fq,sample3.fq} + +For paired-end reads, use comma separated list +for read1, followed by space, followed by comma separated list for read2, e.g.: + +\opt{readFilesIn}~\optv{s1read1.fq,s2read1.fq,s3read1.fq s1read2.fq,s2read2.fq,s3read2.fq} + +For multiple read files, the corresponding read groups can be supplied with space/comma/space-separated list in \opt{outSAMattrRGline}, e.g. + +\opt{outSAMattrRGline} \optv{ID:sample1 , ID:sample2 , ID:sample3} + +Note that this list is separated by commas surrounded by spaces (unlike \opt{readFilesIn} list). + +Another option for mapping multiple reads files, especially convenient for a very large number of files, is to create a file manifest and supply it in \opt{readFilesManifest} \optv{/path/to/manifest.tsv}. +The manifest file should contain 3 tab-separated columns. For paired-end reads: + +\ofilen{read1-file-name $tab$ read2-file-name $tab$ read-group-line} + +For single-end reads, the 2nd column should contain the dash -: + +\ofilen{read1-file-name $tab$ - $tab$ read-group-line} + +Spaces, but not tabs are allowed in the file names. +If read-group-line does not start with ID:, it can only contain one ID field, and ID: will be added to it. +If read-group-line starts with ID:, it can contain several fields separated by $tab$, and all the fields will be copied verbatim into SAM @RG header line. + \subsection{Advanced options.} -There are many advanced options that control STAR mapping behavior. All options are briefly described in the Section \sechyperref{Description_of_all_options}. +There are many advanced options that control STAR mapping behavior. All options are briefly described in the Section \sechyperref{Description_of_all_options}. \subsubsection{Using annotations at the mapping stage.} -Since 2.4.1a, the annotations can be included on the fly at the mapping step, without including them at the genome generation step. You can specify \opt{sjdbGTFfile} \optvr{/path/to/ann.gtf} and/or \opt{sjdbFileChrStartEnd} \optvr{/path/to/sj.tab}, as well as \opt{sjdbOverhang}, and any other \opt{sjdb*} options. The genome indices can be generated with or without another set of annotations/junctions. In the latter case the new junctions will added to the old ones. STAR will insert the junctions into genome indices on the fly before mapping, which takes 1~2 minutes. The on the fly genome indices can be saved (for reuse) with \opt{sjdbInsertSave} \optv{All}, into \optvr{\_STARgenome} directory inside the current run directory. +Since 2.4.1a, the annotations can be included on the fly at the mapping step, without including them at the genome generation step. You can specify \opt{sjdbGTFfile} \optvr{/path/to/ann.gtf} and/or \opt{sjdbFileChrStartEnd} \optvr{/path/to/sj.tab}, as well as \opt{sjdbOverhang}, and any other \opt{sjdb*} options. The genome indices can be generated with or without another set of annotations/junctions. In the latter case the new junctions will added to the old ones. STAR will insert the junctions into genome indices on the fly before mapping, which takes 1~2 minutes. The on the fly genome indices can be saved (for reuse) with \opt{sjdbInsertSave} \optv{All}, into \optvr{\_STARgenome} directory inside the current run directory. \subsubsection{ENCODE options} An example of ENCODE standard options for long RNA-seq pipeline is given below: @@ -194,7 +227,7 @@ \subsubsection{ENCODE options} \item[] \opt{outFilterType} BySJout\\ reduces the number of "spurious" junctions -\item[] +\item[] \opt{outFilterMultimapNmax} 20\\ max number of multiple alignments allowed for a read: if exceeded, the read is considered unmapped \item[] @@ -221,7 +254,7 @@ \subsubsection{ENCODE options} \end{itemize} \subsection{Using shared memory for the genome indexes.} -The \opt{genomeLoad} option controls how the genome is loaded into memory. By default, \opt{genomeLoad} \optvr{NoSharedMemory}, shared memory is not used. +The \opt{genomeLoad} option controls how the genome is loaded into memory. By default, \opt{genomeLoad} \optvr{NoSharedMemory}, shared memory is not used. With \opt{genomeLoad} \optvr{LoadAndKeep}, STAR loads the genome as a standard Linux shared memory piece. The genomes are identified by their unique directory paths. Before loading the genome, STAR checks if the genome has already been loaded into the shared memory. If the genome has not been loaded, STAR will load it and will keep it in memory even after STAR job finishes. The genome will be shared with all the other STAR jobs. You can remove the genome from the shared memory running STAR with \opt{genomeLoad} \optvr{Remove}. The shared memory piece will be physically removed only after all STAR jobs attached to it complete. With \opt{genomeLoad} \optvr{LoadAndRemove}, STAR will load genome in the shared memory, and mark it for removal, so that the genome will be removed from the shared memory once all STAR jobs using it exit. \opt{genomeLoad} \optvr{LoadAndExit}, STAR will load genome in the shared memory, and immediately exit, keeping the genome loaded in the shared memory for the future runs. @@ -238,6 +271,13 @@ \subsection{Using shared memory for the genome indexes.} \code{/sbin/sysctl -p}\\ This will increase the allowed shared memory blocks to ~31GB, enough for human or mouse genome. +\section{Output filtering.}\label{Output_filtering} +\subsection{Multimappers.} +The output of multimappers (i.e. reads mapping to multiple loci) is controlled by +\opt{outFilterMultimapNmax} \optv{N}. By default, \optv{N}=10. If a read maps to $\le$\optv{N} loci, it will be output, otherwise, it will be considered as unmapped and reported as "Multimapping: mapped to too many loci" in the \ofilen{Log.final.out} summary statistics file. + +The detection of multimappers is controlled by \opt{winAnchorMultimapNmax} option, =\optv{50} by default. This parameter should be set to at least the number of multimapping loci, i.e. \opt{winAnchorMultimapNmax} $\ge$ \opt{outFilterMultimapNmax}. Note that this parameter also controls the overall sensitivity of mapping: increasing it will change (improve) the mapping of unique mappers as well, though at the cost of slower speed. + \section{Output files.}\label{Output_files} STAR produces multiple output files. All files have standard name, however, you can change the file prefixes using \opt{outFileNamePrefix} \optvr{/path/to/output/dir/prefix}. By default, this parameter is \optv{./}, i.e. all output files are written in the current directory. \subsection{Log files.} @@ -262,32 +302,87 @@ \subsubsection{Multimappers.} By default, the order of the multi-mapping alignments for each read is not truly random. The \opt{outMultimapperOrder} \optv{Random} option outputs multiple alignments for each read in random order, and also also randomizes the choice of the primary alignment from the highest scoring alignments. Parameter \opt{runRNGseed} can be used to set the random generator seed. With this option, the ordering of multi-mapping alignments of each read, and the choice of the primary alignment will vary from run to run, unless only one thread is used and the seed is kept constant. -The \opt{outSAMmultNmax} parameter limits the number of output alignments (SAM lines) for multimappers. For instance, \opt{outSAMmultNmax} \optv{1} will output exactly one SAM line for each mapped read. Note that \code{NH:i:} tag in STAR will still report the actual number of loci that the reads map to, while the the number of reported alignments for a read in the SAM file is \code{min(NH,--outSAMmultNMax)}. +The \opt{outSAMmultNmax} parameter limits the number of output alignments (SAM lines) for multimappers. For instance, \opt{outSAMmultNmax} \optv{1} will output exactly one SAM line for each mapped read. Note that \code{NH:i:} tag in STAR will still report the actual number of loci that the reads map to, while the the number of reported alignments for a read in the SAM file is \code{min(NH,--outSAMmultNMax)}. If \opt{outSAMmultNmax} is equal to \optv{-1}, all the alignments are output according to the order specified in \opt{outMultimapperOrder} option. If \opt{outSAMmultNmax} is not equal to -1, than top-scoring alignments will always be output first, even for the default \opt{outMultimapperOrder} \optv{Old\_2.4} option. \subsubsection{SAM attributes.} -The SAM attributes can be specified by the user using \opt{outSAMattributes} \optvr{A1 A2 A3 ...} option which accept a list of 2-character SAM attributes. The implemented attributes are: \optv{NH HI NM MD AS nM jM jI XS}. By default, STAR outputs \optv{NH HI AS nM} attributes. -\begin{itemize} +The SAM attributes can be specified by the user using \opt{outSAMattributes} \optvr{A1 A2 A3 ...} option which accept a list of 2-character SAM attributes. The attributes can be listed in any order, and will be recorded in that order in the SAM file. By default, STAR outputs \optv{NH HI AS nM} attributes. + +\begin{itemize}[itemsep=1pt] +\item[] +\textbf{Presets:} +% +\item[] +\optv{None} : No SAM attributes +% \item[] -\optv{NH HI NM MD} : have standard meaning as defined in the SAM format specifications. +\optv{Standard} : NH HI AS nM +% \item[] -\optv{AS} : id the local alignment score (paired for paired-end reads). +\optv{All} : NH HI AS nM NM MD jM jI MC ch + +\textbf{Alignment:} +% +\item[] +\optv{NH} : number of loci the reads maps to: $=1$ for unique mappers, $>1$ for multimappers. Standard SAM tag. +% +\item[] +\optv{HI} : multiple alignment index, starts with --outSAMattrIHstart ($=1$ by default). Standard SAM tag. +% +\item[] +\optv{AS} : local alignment score, $+1/-1$ for matches/mismateches, score* penalties for indels and gaps. For PE reads, total score for two mates. Standard SAM tag. +% \item[] -\optv{nM} : is the number of mismatches per (paired) alignment, not to be confused with \optv{NM}, which is the number of mismatches in each mate. +\optv{NM} : edit distance to the reference (number of mismatched + inserted + deleted bases) for each mate. Standard SAM tag. +% +\item[] +\optv{nM} : number of mismatches per (paired) alignment, not to be confused with \optv{NM}, which is the number of mismatches+indels in each mate. +% \item[] \optv{jM:B:c,M1,M2,...} : intron motifs for all junctions (i.e. N in CIGAR): 0: non-canonical; 1: GT/AG, 2: CT/AC, 3: GC/AG, 4: CT/GC, 5: AT/AC, 6: GT/AT. If splice junctions database is used, and a junction is annotated, 20 is added to its motif value. +% +\item[] +\optv{MD} : string encoding mismatched and deleted reference bases (see standard SAM specifications). Standard SAM tag. +% \item[] \optv{jI:B:I,Start1,End1,Start2,End2,...} : Start and End of introns for all junctions (1-based). +% \item[] \optv{jM jI} : attributes require samtools 0.1.18 or later, and were reported to be incompatible with some downstream tools such as Cufflinks. + +\textbf{Variation:} +% +\item[] +\optv{vA} : variant allele. +% \item[] -\optv{vA} : variant allele +\optv{vG} : genomic coordinate of the variant overlapped by the read. +% \item[] -\optv{vG} : genomic coordiante of the variant overlapped by the read +\optv{vW} : WASP filtering tag, see detailed description in Section \ref{section:WASP}. Requires \opt{waspOutputMode} \optv{SAMtag}. + +\textbf{STARsolo:} +% +\item[] +\optv{CR CY UR UY} : sequences and quality scores of cell barcodes and UMIs for the solo* demultiplexing, not error corrected. +% +\item[] +\optv{GX GN} : gene ID and name. +% \item[] -\optv{vW} : 0/1 - alignment does not pass / passes WASP filtering. Requires --waspOutputMode SAMtag +\optv{CB UB} : error-corrected cell barcodes and UMIs for solo* demultiplexing. Requires \opt{outSAMtype} \optv{BAM SortedByCoordinate}. +% \item[] -\optv{CR CY UR UY} : sequences and quality scores of cell barcodes and UMIs for the solo* demultiplexing, not error corrected +\optv{sM} : assessment of CB and UMI. +% +\item[] +\optv{sS} : sequence of the entire barcode (CB,UMI,adapter...). +% +\item[] +\optv{sQ} : quality of the entire barcode. + + +\textbf{Unmapped reads:} \item[] \optv{uT} : for unmapped reads, reason for not mapping: \begin{itemize}[noitemsep,topsep=-3pt] @@ -316,14 +411,35 @@ \subsection{Unsorted and sorted-by-coordinate BAM.} output unsorted \ofilen{Aligned.out.bam} file. The paired ends of an alignment are always adjacent, and multiple alignments of a read are adjacent as well. This "unsorted" file can be directly used with downstream software such as \code{HTseq}, without the need of name sorting. The order of the reads will match that of the input FASTQ(A) files only if one thread is used \opt{runThread} \optv{1}, and \opt{outFilterType} \opt{BySJout} is \textbf{not} used. \item[] \opt{outSAMtype} \optv{BAM SortedByCoordinate}\\ -output sorted by coordinate \ofilen{Aligned.sortedByCoord.out.bam} file, similar to \code{samtools sort} command. +output sorted by coordinate \ofilen{Aligned.sortedByCoord.out.bam} file, similar to \code{samtools sort} command. If this option causes problems, it is recommended to reduce \opt{outBAMsortingThreadN} from the default $6$ to lower values (as low as 1). \item[] \opt{outSAMtype} \optv{BAM Unsorted SortedByCoordinate}\\ output both unsorted and sorted files. \end{itemize} +\subsection{Unmapped reads.} +Unmapped reads can be output into the SAM/BAM \ofilen{Aligned.*} file(s) with +\opt{outSAMunmapped} \optv{Within} option. \opt{outSAMunmapped} \optv{Within KeepPairs} will (redundantly) record unmapped mate for each alignment, and, in case of unsorted output, keep it adjacent to its mapped mate (this only affects multi-mapping reads). +\optv{uT} SAM tag indicates reason for not mapping: +\begin{itemize}[noitemsep] + \item[] 0 : no acceptable seed/windows, "Unmapped other" in the Log.final.out + \item[] 1 : best alignment shorter than min allowed mapped length, "Unmapped: too short" in the Log.final.out + \item[] 2 : best alignment has more mismatches than max allowed number of mismatches, "Unmapped: too many mismatches" in the Log.final.out + \item[] 3 : read maps to more loci than the max number of multimappng loci, "Multimapping: mapped to too many loci" in the Log.final.out + \item[] 4 : unmapped mate of a mapped paired-end read +\end{itemize} + +\opt{outReadsUnmapped} \optv{Fastx} will output unmapped reads into separate file(s) \ofilen{Unmapped.out.mate1[2]}, formatted the same way as input read files (i.e. FASTQ or FASTA). +For paired-end reads, if a read maps as a whole, but one of the mates does not map, both mates will also be output in \ofilen{Unmapped.out.mate1/2} files. +To indicate the mapping status of the read mates, the following tags are appended to the read name: +\begin{itemize}[noitemsep,topsep=-3pt] + \item[] $00$: mates were not mapped; + \item[] $10$: 1st mate mapped, 2nd unmapped + \item[] $01$: 1st unmapped, 2nd mapped +\end{itemize} + \subsection{Splice junctions.} -\ofilen{SJ.out.tab} contains high confidence collapsed splice junctions in tab-delimited format. +\ofilen{SJ.out.tab} contains high confidence collapsed splice junctions in tab-delimited format. Note that STAR defines the junction start/end as intronic bases, while many other software define them as exonic bases. The columns have the following meaning: %\begin{enumerate}[label=\bfseries Exercise \arabic*:] @@ -333,10 +449,10 @@ \subsection{Splice junctions.} \item[column 3:] last base of the intron (1-based) \item[column 4:] strand (0: undefined, 1: +, 2: -) \item[column 5:] intron motif: 0: non-canonical; 1: GT/AG, 2: CT/AC, 3: GC/AG, 4: CT/GC, 5: AT/AC, 6: GT/AT -\item[column 6:] 0: unannotated, 1: annotated (only if splice junctions database is used) +\item[column 6:] 0: unannotated, 1: annotated in the splice junctions database. Note that in 2-pass mode, junctions detected in the 1st pass are reported as annotated, in addition to annotated junctions from GTF. \item[column 7:] number of uniquely mapping reads crossing the junction \item[column 8:] number of multi-mapping reads crossing the junction -\item[column 9:] maximum spliced alignment overhang +\item[column 9:] maximum spliced alignment overhang \end{itemize} The filtering for this output file is controlled by the \optn{outSJfilter*} parameters, as described in \sechyperref{Output_Filtering:_Splice_Junctions}. %\subsection{Wiggle/bedGraph.} @@ -349,7 +465,7 @@ \subsection{STAR-Fusion.} \subsection{Chimeric alignments in the main BAM files.} Chimeric alignments can be included together with normal alignments in the main (sorted or unsorted) BAM file(s) using \opt{chimOutType} \optv{WithinBAM}. In these files, formatting of chimeric alignments follows the latest SAM/BAM specifications. - + \subsection{Chimeric alignments in \ofilen{Chimeric.out.sam} .} With \opt{chimOutType} \optv{SeparateSAMold} STAR will output normal alignments into \ofilen{Aligned.*.sam/bam}, and will output chimeric alignments into a separate file \ofilen{Chimeric.out.sam}. Note that this option will be deprecated in the future, and the \opt{chimOutType} \optv{WithinBAM} is strongly recommended. Some reads may be output to both normal SAM/BAM files, and \ofilen{Chimeric.out.sam} for the following reason. STAR will output a non-chimeric alignment into \ofilen{Aligned.out.sam} with soft-clipping a portion of the read. If this portion is long enough, and it maps well and uniquely somewhere else in the genome, there will also be a chimeric alignment output into \ofilen{Chimeric.out.sam}. For instance, if you have a paired-end read where the second mate can be split chimerically into 70 and 30 bases. The 100b of the first mate + 70b of the 2nd mate map non-chimerically,and the mapping length/score are big enough, so they will be output into \ofilen{Aligned.out.sam} file. At the same time, the chimeric segments 100-mate1 + 70-mate2 and 30-mate2 will be output into \ofilen{Chimeric.out.sam}. @@ -358,7 +474,7 @@ \subsection{Chimeric alignments in \ofilen{Chimeric.out.junction}} By default, or with \opt{chimOutType} \optv{Junctions}, STAR will generate \ofilen{Chimeric.out.junction} file which maybe more convenient for downstream analysis. The format of this file is as follows. Every line contains one chimerically aligned read, e.g.: \begin{verbatim} -chr22 23632601 + chr9 133729450 + 1 0 0 +chr22 23632601 + chr9 133729450 + 1 0 0 SINATRA-0006:3:3:6387:5665#0 23632554 47M29S 133729451 47S29M40p76M \end{verbatim} @@ -396,7 +512,7 @@ \subsection{Chimeric alignments in \ofilen{Chimeric.out.junction}} \end{itemize} Unlike standard SAM, both mates are recorded in one line here. The gap of length \code{L} between the mates is marked by the \code{p} in the CIGAR string. -If the mates overlap, \code{L<0}. +If the mates overlap, \code{L<0}. For strand definitions, when aligning paired end reads, the sequence of the second mate is reverse complemented. @@ -404,8 +520,8 @@ \subsection{Chimeric alignments in \ofilen{Chimeric.out.junction}} To filter chimeric junctions and find the number of reads supporting each junction you could use, for example: \begin{verbatim} -cat Chimeric.out.junction | -awk '$1!="chrM" && $4!="chrM" && $7>0 && $8+$9<=5 {print $1,$2,$3,$4,$5,$6,$7,$8,$9}' | +cat Chimeric.out.junction | +awk '$1!="chrM" && $4!="chrM" && $7>0 && $8+$9<=5 {print $1,$2,$3,$4,$5,$6,$7,$8,$9}' | sort | uniq -c | sort -k1,1rn \end{verbatim} This will keep only the canonical junctions with the repeat length less than 5 and will remove chimeras with mitochondrion genome. @@ -423,7 +539,7 @@ \subsection{Chimeric alignments in \ofilen{Chimeric.out.junction}} 15 chr3 197348574 - chr3 195392936 + 1 1 0 14 chr18 39584506 + chr18 39560613 - 1 2 0 \end{verbatim} -Note that line 4 and 6 here are BCR/ABL fusions. You would need to filter these junctions further to see which of them connect known but not homologous genes. +Note that line 4 and 6 here are BCR/ABL fusions. You would need to filter these junctions further to see which of them connect known but not homologous genes. \section{Output in transcript coordinates.} @@ -431,16 +547,13 @@ \section{Output in transcript coordinates.} Note, that STAR first aligns reads to entire genome, and only then searches for concordance between alignments and transcripts.This approach offers certain advantages compared to the alignment to transcriptome only, by not forcing the alignments to annotated transcripts. Note that \opt{outFilterMultimapNmax} filter only applies to genomic alignments. If an alignment passes this filter, it is converted to all possible transcriptomic alignments and all of them are output. - - - -By default, the output satisfies RSEM requirements: soft-clipping or indels are not allowed. Use \opt{quantTranscriptomeBan} \optv{Singleend} to allow insertions, deletions ans soft-clips in the transcriptomic alignments, which can be used by some expression quantification software (e.g. eXpress). +By default, the output satisfies RSEM requirements: soft-clipping or indels are not allowed. Use \opt{quantTranscriptomeBan} \optv{Singleend} to allow insertions, deletions ans soft-clips in the transcriptomic alignments, which can be used by some expression quantification software (e.g. eXpress). \section{Counting number of reads per gene.} -With \opt{quantMode} \optv{GeneCounts} option STAR will count number reads per gene while mapping. -A read is counted if it overlaps (1nt or more) one and only one gene. Both ends of the paired-end read are checked for overlaps. +With \opt{quantMode} \optv{GeneCounts} option STAR will count number reads per gene while mapping. +A read is counted if it overlaps (1nt or more) one and only one gene. Both ends of the paired-end read are checked for overlaps. The counts coincide with those produced by htseq-count with default parameters. -This option requires annotations (GTF or GFF with --sjdbGTFfile option) used at the genome generation step, or at the mapping step. +This option requires annotations in GTF format (i.e. \emph{gene\_id} tag for each exon) specified in \opt{sjdbGTFfile} at the genome generation step or at the mapping step provided in option. STAR outputs read counts per gene into ReadsPerGene.out.tab file with 4 columns which correspond to different strandedness options: \begin{itemize}[leftmargin=1in] \item[column 1:] gene ID @@ -455,7 +568,7 @@ \section{Counting number of reads per gene.} \section{2-pass mapping.} -For the most sensitive novel junction discovery,I would recommend running STAR in the 2-pass mode. It does not increase the number of detected novel junctions, but allows to detect more splices reads mapping to novel junctions. The basic idea is to run 1st pass of STAR mapping with the usual parameters, then collect the junctions detected in the first pass, and use them as "annotated" junctions for the 2nd pass mapping. +For the most sensitive novel junction discovery, it is recommended to run STAR in the 2-pass mode. It does not significantly increase the number of detected novel junctions, but allows to detect more splices reads mapping to novel junctions. The basic idea is to run 1st pass of STAR mapping with the usual parameters, then collect the junctions detected in the first pass, and use them as "annotated" junctions for the 2nd pass mapping. \subsection{Multi-sample 2-pass mapping.} For a study with multiple samples, it is recommended to collect 1st pass junctions from all samples. @@ -465,7 +578,7 @@ \subsection{Multi-sample 2-pass mapping.} \end{enumerate} \subsection{Per-sample 2-pass mapping.} - + Annotated junctions will be included in both the 1st and 2nd passes. To run STAR 2-pass mapping for each sample separately, use \opt{twopassMode} \optv{Basic} option. STAR will perform the 1st pass mapping, then it will automatically extract junctions, insert them into the genome index, and, finally, re-map all reads in the 2nd mapping pass. This option can be used with annotations, which can be included either at the run-time (see \#1), or at the genome generation step. @@ -484,22 +597,22 @@ \section{Merging and mapping of overlapping paired-end reads.} This feature improves mapping accuracy for paired-end libraries with short insert sizes, where many reads have overlapping mates. Importantly, it allows detection of chimeric junction in the overlap region. STAR will search for an overlap between mates larger or equal to \opt{peOverlapNbasesMin} bases with proportion of mismatches in the overlap area not exceeding \opt{peOverlapMMp}. -If the overlap is found, STAR will map merge the mates and attempt to map the resulting (single-end) sequence. +If the overlap is found, STAR will map merge the mates and attempt to map the resulting (single-end) sequence. If requested, the chimeric detection will be performed on the merged-mate sequence, thus allowing chimeric detection in the overlap region. If the score of this alignment higher than the original one, or if a chimeric alignment is found, STAR will report the merged-mate aligment instead of the original one. In the output, the merged-mate aligment will be converted back to paired-end format. -The developmment of this algorithm was supported by Illumina, Inc. +The developmment of this algorithm was supported by Illumina, Inc. Many thanks to June Snedecor, Xiao Chen, and Felix Schlesinger for their extensive help in developing this feature. \section{Detection of personal variants overlapping alignments.} -Option \opt{varVCFfile} \optvr{/path/to/vcf/file} is used to input VCF file with personal variants. Only single nucleotide variants (SNVs) are supported at the moment. +Option \opt{varVCFfile} \optvr{/path/to/vcf/file} is used to input VCF file with personal variants. Only single nucleotide variants (SNVs) are supported at the moment. Each variant is expected to have a genotype with two alleles. -To output variants that overlap alignments, vG and vA have to be added to \opt{outSAMattributes} list. +To output variants that overlap alignments, vG and vA have to be added to \opt{outSAMattributes} list. SAM attribute vG outputs the genomic coordinate of the variant, allowing for identification of the variant. SAM attribute vA outputs which allele is detected in the read: $1$ or $2$ match one of the genotype alleles, $3$ - no match to genotype. -\section{WASP filtering of allele specific alignments.} +\section{WASP filtering of allele specific alignments.} \label{section:WASP} This is re-implementation of the original WASP algorithm by Bryce van de Geijn, Graham McVicker, Yoav Gilad and Jonathan K Pritchard. Please cite the original WASP paper: Nature Methods 12, 1061–1063 (2015) \url{https://www.nature.com/articles/nmeth.3582}. WASP filtering is activated with \opt{waspOutputMode} \optv{SAMtag}, which will add \optv{vW} tag to the SAM output: \optv{vW:i:1} means alignment passed WASP filtering, and all other values mean it did not pass: @@ -516,12 +629,28 @@ \section{WASP filtering of allele specific alignments.} \optv{vW:i:7} - read overlaps too many variants +\section{STARconsensus} +STARconsensus allows for mapping RNA-seq reads to consensus genome. It was introduced in STAR 2{.}7{.}7a (2020/12/28). + +\begin{itemize} +\item +Provide the VCF file with consensus SNVs and InDels at the genome generation stage with \opt{genomeTransformVC} \optv{ Variants.vcf} \opt{genomeTransformType} \optv{Haploid}. +The alternative alleles in this VCF will be inserted to the reference genome to create a "transformed" genome. +Both the genome sequence and transcript/gene annotations are transformed. + +\item +At the mapping stage, the reads will be mapped to the tranformed (consensus) genome. +The quantification in the transformed annotations can be performed with standard \opt{quantMode} \optv{TranscriptomeSAM} and/or \optv{GeneCounts} options. +If desired, alignments (SAM/BAM) and spliced junctions (SJ.out.tab) can be transformed back to the original (reference) coordinates with \opt{genomeTransformOutput} \optv{SAM} and/or \optv{SJ}. +This is useful if downstream processing relies on reference coordinates. +\end{itemize} + \section{Detection of multimapping chimeras.} Previous STAR chimeric detection algorithm only detected uniquely mapping chimeras, which reduced its sensitivity in some cases. The new algorithm can detect and output multimapping chimeras. Presently, the only output into Chimeric.out.junction is supported. This algorithm is activated with $>0$ value in \optv{chimMultimapNmax}, which defines the maximum number of chimeric multi-alignments. The \optv{chimMultimapScoreRange} ($=1$ by default) parameter defines the score range for multi-mapping chimeras below the best chimeric score, similar to the \optv{outFilterMultimapScoreRange} parameter for normal alignments. -The \optv{chimNonchimScoreDropMin} ($=20$ by default) defines the threshold triggering chimeric detection: the drop in the best non-chimeric alignment score with respect to the read length has to be smaller than this value. +The \optv{chimNonchimScoreDropMin} ($=20$ by default) defines the threshold triggering chimeric detection: the drop in the best non-chimeric alignment score with respect to the read length has to be greater than this value. \section{STARsolo: mapping, demultiplexing and gene quantification for single cell RNA-seq} @@ -529,9 +658,9 @@ \section{STARsolo: mapping, demultiplexing and gene quantification for single ce STARsolo inputs the raw FASTQ reads files, and performs the following operations: \begin{itemize} \itemsep -0.5em - \item + \item error correction and demultiplexing of cell barcodes using user-input whitelist - \item + \item mapping the reads to the reference genome using the standard STAR spliced read alignment algorithm \item error correction and collapsing (deduplication) of Unique Molecular Identifiers (UMIa) @@ -541,26 +670,15 @@ \section{STARsolo: mapping, demultiplexing and gene quantification for single ce STARsolo output is designed to be a drop-in replacement for 10X CellRanger gene quantification output. It follows CellRanger logic for cell barcode whitelisting and UMI deduplication, and produces nearly identical gene counts in the same format. At the same time STARsolo is ~10 times faster than the CellRanger. -The STAR solo algorithm is turned on with: \opt{soloType} \optv{Droplet}. - -Presently, the cell barcode whitelist has to be provided with: - -\opt{soloCBwhitelist} \optvr{/path/to/cell/barcode/whitelist} - -The 10X Chromium whitelist file can be found inside the CellRanger distribution, e.g. \url{https://kb.10xgenomics.com/hc/en-us/articles/115004506263-What-is-a-barcode-whitelist-}. Please make sure that the whitelist is compatible with the specific version of the 10X chemistry (V1,V2,V3 etc). - -Importantly, in the --readFilesIn option, the 1st FASTQ file has to be cDNA read, and the 2nd FASTQ file has to be the barcode (cell+UMI) read, i.e. - -\opt{readFilesIn} \optvr{cDNAfragmentSequence.fastq.gz CellBarcodeUMIsequence.fastq.gz}. - -Other solo* options can be found in the Section \ref{STARsolo_(single_cell_RNA-seq)_parameters}. +STARsolo solo* options can be found in the Section \ref{STARsolo_(single_cell_RNA-seq)_parameters}. +For more detailed description, please see \url{https://github.com/alexdobin/STAR/blob/master/docs/STARsolo.md}. \subsection{Feature statistics summaries.} Feature statistics summaries are recorded in the \optvr{Solo.out/} directory in files \optvr{.stats} where features are those used in the \opt{soloFeatures} option, e.g. \optvr{Gene.stats}. The following metrics are recorded: \begin{itemize}[leftmargin=1.5in] \itemsep -0.3em \item[\optv{nNinBarcode:}] number of reads with more than 2 Ns in cell barcode (CB) - \item[\optv{nUMIhomopolymer:}] number of reads with homopolymer in CB + \item[\optv{nUMIhomopolymer:}] number of reads with homopolymer in CB \item[\optv{nTooMany:}] not used at the moment \item[\optv{nNoMatch:}] number of reads with CBs that do not match whitelist even with one mismatch \end{itemize} @@ -592,7 +710,7 @@ \subsection{Feature statistics summaries.} \end{itemize} The three categoties above summed together should be equal to the total number of reads. - + \section{Description of all options.}\label{Description_of_all_options} For each STAR version, the most up-to-date information about all STAR parameters can be found in the \code{parametersDefault} file in the STAR source directory. The parameters in the \code{parametersDefault}, as well as in the descriptions below, are grouped by function: \begin{itemize} @@ -600,7 +718,7 @@ \section{Description of all options.}\label{Description_of_all_options} \item[] In particular, \optn{outFilter*} parameters control the filtering of output alignments which[] you might want to tweak to fit your needs. \item[] Output of “chimeric” alignments is controlled by \optn{chim*} parameters. \item[] Genome generation is controlled by \optn{genome*} parameters. -\item[] Annotations (splice junction database) are controlled by \optn{sjdb*} options at the genome generation step. +\item[] Annotations (splice junction database) are controlled by \optn{sjdb*} options at the genome generation step. \item[] Tweaking \optn{score*}, \optn{align*}, \optn{seed*}, \optn{win*} parameters, which requires understanding of the STAR alignment algorithm, is recommended only for advanced users. \end{itemize} diff --git a/extras/doc-latex/convertParDefToLatexTable.awk b/extras/doc-latex/convertParDefToLatexTable.awk index 306ac2ca..445d6b69 100644 --- a/extras/doc-latex/convertParDefToLatexTable.awk +++ b/extras/doc-latex/convertParDefToLatexTable.awk @@ -15,7 +15,15 @@ BEGIN { }; { + +if ($0 ~ /^#####UnderDevelopment_begin/) { + while ($0 !~ /^#####UnderDevelopment_end/) { + getline; + }; +}; + substLatexSymbols(); + if ($1=="###") {# new group/subsection of parameters if ($2!="versions") {# skip versions if (nSection>0) print optTableEnd; @@ -27,7 +35,7 @@ if ($1=="###") {# new group/subsection of parameters ++nSection; }; } else if ($0!="" && substr($0,1,1)!=" " && substr($1,1,1)!="#" && substr($1,1,7)!="version") {//option name has a letter as the first character - optV=$2; + optV=$2; for (ii=3;ii<=NF;ii++) optV=optV " " $ii; print "\\optName{" $1 "}"; print " \\optValue{" optV "}"; diff --git a/extras/doc-latex/parametersDefault.tex b/extras/doc-latex/parametersDefault.tex index cbc8723a..79b1c103 100644 --- a/extras/doc-latex/parametersDefault.tex +++ b/extras/doc-latex/parametersDefault.tex @@ -18,6 +18,13 @@ \optName{runMode} \optValue{alignReads} \optLine{string: type of the run.} +\begin{optOptTable} + \optOpt{alignReads} \optOptLine{map reads} + \optOpt{genomeGenerate} \optOptLine{generate genome files} + \optOpt{inputAlignmentsFromBAM} \optOptLine{input alignments from BAM. Presently only works with --outWigType and --bamRemoveDuplicates options.} + \optOpt{liftOver} \optOptLine{lift-over of GTF files (--sjdbGTFfile) between genome assemblies using chain file(s) from --genomeChainFiles.} + \optOpt{soloCellFiltering {\textless}/path/to/raw/count/dir/{\textgreater} {\textless}/path/to/output/prefix{\textgreater}} \optOptLine{STARsolo cell filtering ("calling") without remapping, followed by the path to raw count directory and output (filtered) prefix} +\end{optOptTable} \optName{runThreadN} \optValue{1} \optLine{int: number of threads to run STAR} @@ -57,9 +64,14 @@ \optName{genomeFileSizes} \optValue{0} \optLine{uint(s){\textgreater}0: genome files exact sizes in bytes. Typically, this should not be defined by the user.} -\optName{genomeConsensusFile} - \optValue{-} - \optLine{string: VCF file with consensus SNPs (i.e. alternative allele is the major (AF{\textgreater}0.5) allele)} +\optName{genomeTransformOutput} + \optValue{None} + \optLine{string(s) which output to transform back to original genome} +\begin{optOptTable} + \optOpt{SAM} \optOptLine{SAM/BAM alignments} + \optOpt{SJ} \optOptLine{splice junctions (SJ.out.tab)} + \optOpt{None} \optOptLine{no transformation of the output} +\end{optOptTable} \end{optTable} \optSection{Genome Indexing Parameters - only used with --runMode genomeGenerate}\label{Genome_Indexing_Parameters_-_only_used_with_--runMode_genomeGenerate} \begin{optTable} @@ -75,6 +87,17 @@ \optName{genomeSuffixLengthMax} \optValue{-1} \optLine{int: maximum length of the suffixes, has to be longer than read length. -1 = infinite.} +\optName{genomeTransformType} + \optValue{None} + \optLine{string: type of genome transformation} +\begin{optOptTable} + \optOpt{None} \optOptLine{no transformation} + \optOpt{Haploid} \optOptLine{replace reference alleles with alternative alleles from VCF file (e.g. consensus allele)} + \optOpt{Diploid} \optOptLine{create two haplotypes for each chromosome listed in VCF file, for genotypes 1|2, assumes perfect phasing (e.g. personal genome)} +\end{optOptTable} +\optName{genomeTransformVCF} + \optValue{-} + \optLine{string: path to VCF file for genome transformation} \end{optTable} \optSection{Splice Junctions Database}\label{Splice_Junctions_Database} \begin{optTable} @@ -107,7 +130,7 @@ \optLine{int{\textgreater}0: length of the donor/acceptor sequence on each side of the junctions, ideally = (mate{\textunderscore}length - 1)} \optName{sjdbScore} \optValue{2} - \optLine{int: extra alignment score for alignmets that cross database junctions} + \optLine{int: extra alignment score for alignments that cross database junctions} \optName{sjdbInsertSave} \optValue{Basic} \optLine{string: which files to save when sjdb junctions are inserted on the fly at the mapping step} @@ -120,7 +143,7 @@ \begin{optTable} \optName{varVCFfile} \optValue{-} - \optLine{string: path to the VCF file that contains variation data.} + \optLine{string: path to the VCF file that contains variation data. The 10th column should contain the genotype information, e.g. 0/1} \end{optTable} \optSection{Input Files}\label{Input_Files} \begin{optTable} @@ -138,13 +161,27 @@ \optOpt{SAM SE} \optOptLine{SAM or BAM single-end reads; for BAM use --readFilesCommand samtools view} \optOpt{SAM PE} \optOptLine{SAM or BAM paired-end reads; for BAM use --readFilesCommand samtools view} \end{optOptTable} +\optName{readFilesSAMattrKeep} + \optValue{All} + \optLine{string(s): for --readFilesType SAM SE/PE, which SAM tags to keep in the output BAM, e.g.: --readFilesSAMtagsKeep RG PL} +\begin{optOptTable} + \optOpt{All} \optOptLine{keep all tags} + \optOpt{None} \optOptLine{do not keep any tags} +\end{optOptTable} \optName{readFilesIn} \optValue{Read1 Read2} \optLine{string(s): paths to files that contain input read1 (and, if needed, read2)} +\optName{readFilesManifest} + \optValue{-} + \optLine{string: path to the "manifest" file with the names of read files. The manifest file should contain 3 tab-separated columns:} + \optLine{paired-end reads: read1{\textunderscore}file{\textunderscore}name $tab$ read2{\textunderscore}file{\textunderscore}name $tab$ read{\textunderscore}group{\textunderscore}line.} + \optLine{single-end reads: read1{\textunderscore}file{\textunderscore}name $tab$ - $tab$ read{\textunderscore}group{\textunderscore}line.} + \optLine{Spaces, but not tabs are allowed in file names.} + \optLine{If read{\textunderscore}group{\textunderscore}line does not start with ID:, it can only contain one ID field, and ID: will be added to it.} + \optLine{If read{\textunderscore}group{\textunderscore}line starts with ID:, it can contain several fields separated by $tab$, and all fields will be be copied verbatim into SAM @RG header line.} \optName{readFilesPrefix} \optValue{-} - \optLine{string: preifx for the read files names, i.e. it will be added in front of the strings in --readFilesIn} - \optLine{-: no prefix} + \optLine{string: prefix for the read files names, i.e. it will be added in front of the strings in --readFilesIn} \optName{readFilesCommand} \optValue{-} \optLine{string(s): command line to execute for each of the input file. This command should generate FASTA or FASTQ text and send it to stdout} @@ -159,21 +196,38 @@ \optName{readNameSeparator} \optValue{/} \optLine{string(s): character(s) separating the part of the read names that will be trimmed in output (read name after space is always trimmed)} +\optName{readQualityScoreBase} + \optValue{33} + \optLine{int{\textgreater}=0: number to be subtracted from the ASCII code to get Phred quality score} +\end{optTable} +\optSection{Read Clipping}\label{Read_Clipping} +\begin{optTable} +\optName{clipAdapterType} + \optValue{Hamming} + \optLine{string: adapter clipping type} +\begin{optOptTable} + \optOpt{Hamming} \optOptLine{adapter clipping based on Hamming distance, with the number of mismatches controlled by --clip5pAdapterMMp} + \optOpt{CellRanger4} \optOptLine{5p and 3p adapter clipping similar to CellRanger4. Utilizes Opal package by Martin Šošić: https://github.com/Martinsos/opal} + \optOpt{None} \optOptLine{no adapter clipping, all other clip* parameters are disregarded} +\end{optOptTable} \optName{clip3pNbases} \optValue{0} \optLine{int(s): number(s) of bases to clip from 3p of each mate. If one value is given, it will be assumed the same for both mates.} -\optName{clip5pNbases} - \optValue{0} - \optLine{int(s): number(s) of bases to clip from 5p of each mate. If one value is given, it will be assumed the same for both mates.} \optName{clip3pAdapterSeq} \optValue{-} \optLine{string(s): adapter sequences to clip from 3p of each mate. If one value is given, it will be assumed the same for both mates.} +\begin{optOptTable} + \optOpt{polyA} \optOptLine{polyA sequence with the length equal to read length} +\end{optOptTable} \optName{clip3pAdapterMMp} \optValue{0.1} - \optLine{double(s): max proportion of mismatches for 3p adpater clipping for each mate. If one value is given, it will be assumed the same for both mates.} + \optLine{double(s): max proportion of mismatches for 3p adapter clipping for each mate. If one value is given, it will be assumed the same for both mates.} \optName{clip3pAfterAdapterNbases} \optValue{0} \optLine{int(s): number of bases to clip from 3p of each mate after the adapter clipping. If one value is given, it will be assumed the same for both mates.} +\optName{clip5pNbases} + \optValue{0} + \optLine{int(s): number(s) of bases to clip from 5p of each mate. If one value is given, it will be assumed the same for both mates.} \end{optTable} \optSection{Limits}\label{Limits} \begin{optTable} @@ -181,7 +235,7 @@ \optValue{31000000000} \optLine{int{\textgreater}0: maximum available RAM (bytes) for genome generation} \optName{limitIObufferSize} - \optValue{150000000} + \optValue{30000000 50000000} \optLine{int{\textgreater}0: max available buffers size (bytes) for input/output, per thread} \optName{limitOutSAMoneReadBytes} \optValue{100000} @@ -225,7 +279,7 @@ \optOpt{Log} \optOptLine{log messages} \optOpt{SAM} \optOptLine{alignments in SAM format (which normally are output to Aligned.out.sam file), normal standard output will go into Log.std.out} \optOpt{BAM{\textunderscore}Unsorted} \optOptLine{alignments in BAM format, unsorted. Requires --outSAMtype BAM Unsorted} - \optOpt{BAM{\textunderscore}SortedByCoordinate} \optOptLine{alignments in BAM format, unsorted. Requires --outSAMtype BAM SortedByCoordinate} + \optOpt{BAM{\textunderscore}SortedByCoordinate} \optOptLine{alignments in BAM format, sorted by coordinate. Requires --outSAMtype BAM SortedByCoordinate} \optOpt{BAM{\textunderscore}Quant} \optOptLine{alignments to transcriptome in BAM format, unsorted. Requires --quantMode TranscriptomeSAM} \end{optOptTable} \optName{outReadsUnmapped} @@ -275,25 +329,53 @@ \optLine{string: Cufflinks-like strand field flag} \begin{optOptTable} \optOpt{None} \optOptLine{not used} - \optOpt{intronMotif} \optOptLine{strand derived from the intron motif. Reads with inconsistent and/or non-canonical introns are filtered out.} + \optOpt{intronMotif} \optOptLine{strand derived from the intron motif. This option changes the output alignments: reads with inconsistent and/or non-canonical introns are filtered out.} \end{optOptTable} \optName{outSAMattributes} \optValue{Standard} - \optLine{string: a string of desired SAM attributes, in the order desired for the output SAM} + \optLine{string: a string of desired SAM attributes, in the order desired for the output SAM. Tags can be listed in any combination/order.} + \optLine{***Presets:} \begin{optOptTable} - \optOpt{NH HI AS nM NM MD jM jI XS MC ch} \optOptLine{any combination in any order} \optOpt{None} \optOptLine{no attributes} \optOpt{Standard} \optOptLine{NH HI AS nM} \optOpt{All} \optOptLine{NH HI AS nM NM MD jM jI MC ch} +\end{optOptTable} + \optLine{***Alignment:} +\begin{optOptTable} + \optOpt{NH} \optOptLine{number of loci the reads maps to: =1 for unique mappers, {\textgreater}1 for multimappers. Standard SAM tag.} + \optOpt{HI} \optOptLine{multiple alignment index, starts with --outSAMattrIHstart (=1 by default). Standard SAM tag.} + \optOpt{AS} \optOptLine{local alignment score, +1/-1 for matches/mismateches, score* penalties for indels and gaps. For PE reads, total score for two mates. Stadnard SAM tag.} + \optOpt{nM} \optOptLine{number of mismatches. For PE reads, sum over two mates.} + \optOpt{NM} \optOptLine{edit distance to the reference (number of mismatched + inserted + deleted bases) for each mate. Standard SAM tag.} + \optOpt{MD} \optOptLine{string encoding mismatched and deleted reference bases (see standard SAM specifications). Standard SAM tag.} + \optOpt{jM} \optOptLine{intron motifs for all junctions (i.e. N in CIGAR): 0: non-canonical; 1: GT/AG, 2: CT/AC, 3: GC/AG, 4: CT/GC, 5: AT/AC, 6: GT/AT. If splice junctions database is used, and a junction is annotated, 20 is added to its motif value.} + \optOpt{jI} \optOptLine{start and end of introns for all junctions (1-based).} + \optOpt{XS} \optOptLine{alignment strand according to --outSAMstrandField.} + \optOpt{MC} \optOptLine{mate's CIGAR string. Standard SAM tag.} + \optOpt{ch} \optOptLine{marks all segment of all chimeric alingments for --chimOutType WithinBAM output.} + \optOpt{cN} \optOptLine{number of bases clipped from the read ends: 5' and 3'} +\end{optOptTable} + \optLine{***Variation:} +\begin{optOptTable} \optOpt{vA} \optOptLine{variant allele} - \optOpt{vG} \optOptLine{genomic coordiante of the variant overlapped by the read} - \optOpt{vW} \optOptLine{0/1 - alignment does not pass / passes WASP filtering. Requires --waspOutputMode SAMtag} - \optOpt{CR CY UR UY} \optOptLine{sequences and quality scores of cell barcodes and UMIs for the solo* demultiplexing} + \optOpt{vG} \optOptLine{genomic coordinate of the variant overlapped by the read.} + \optOpt{vW} \optOptLine{1 - alignment passes WASP filtering; 2,3,4,5,6,7 - alignment does not pass WASP filtering. Requires --waspOutputMode SAMtag.} +\end{optOptTable} + \optLine{***STARsolo:} +\begin{optOptTable} + \optOpt{CR CY UR UY} \optOptLine{sequences and quality scores of cell barcodes and UMIs for the solo* demultiplexing.} + \optOpt{GX GN} \optOptLine{gene ID and gene name for unique-gene reads.} + \optOpt{gx gn} \optOptLine{gene IDs and gene names for unique- and multi-gene reads.} + \optOpt{CB UB} \optOptLine{error-corrected cell barcodes and UMIs for solo* demultiplexing. Requires --outSAMtype BAM SortedByCoordinate.} + \optOpt{sM} \optOptLine{assessment of CB and UMI.} + \optOpt{sS} \optOptLine{sequence of the entire barcode (CB,UMI,adapter).} + \optOpt{sQ} \optOptLine{quality of the entire barcode.} \end{optOptTable} - \optLine{Unsupported/undocumented:} + \optLine{***Unsupported/undocumented:} \begin{optOptTable} - \optOpt{rB} \optOptLine{alignment block read/genomic coordinates} - \optOpt{vR} \optOptLine{read coordinate of the variant} + \optOpt{ha} \optOptLine{haplotype (1/2) when mapping to the diploid genome. Requires genome generated with --genomeTransformType Diploid .} + \optOpt{rB} \optOptLine{alignment block read/genomic coordinates.} + \optOpt{vR} \optOptLine{read coordinate of the variant.} \end{optOptTable} \optName{outSAMattrIHstart} \optValue{1} @@ -362,7 +444,7 @@ \end{optOptTable} \optName{outSAMmultNmax} \optValue{-1} - \optLine{int: max number of multiple alignments for a read that will be output to the SAM/BAM files.} + \optLine{int: max number of multiple alignments for a read that will be output to the SAM/BAM files. Note that if this value is not equal to -1, the top scoring alignment will be output first} \begin{optOptTable} \optOpt{-1} \optOptLine{all alignments (up to --outFilterMultimapNmax) will be output} \end{optOptTable} @@ -484,13 +566,25 @@ \optOpt{None} \optOptLine{no filtering} \end{optOptTable} \end{optTable} +\optSection{Output splice junctions (SJ.out.tab)}\label{Output_splice_junctions_(SJ.out.tab)} +\begin{optTable} +\optName{outSJtype} + \optValue{Standard} + \optLine{string: type of splice junction output} +\begin{optOptTable} + \optOpt{Standard} \optOptLine{standard SJ.out.tab output} + \optOpt{None} \optOptLine{no splice junction output} +\end{optOptTable} +\end{optTable} \optSection{Output Filtering: Splice Junctions}\label{Output_Filtering:_Splice_Junctions} \begin{optTable} \optName{outSJfilterReads} \optValue{All} \optLine{string: which reads to consider for collapsed splice junctions output} - \optLine{All: all reads, unique- and multi-mappers} - \optLine{Unique: uniquely mapping reads only} +\begin{optOptTable} + \optOpt{All} \optOptLine{all reads, unique- and multi-mappers} + \optOpt{Unique} \optOptLine{uniquely mapping reads only} +\end{optOptTable} \optName{outSJfilterOverhangMin} \optValue{30 12 12 12} \optLine{4 integers: minimum overhang length for splice junctions on both sides for: (1) non-canonical motifs, (2) GT/AG and CT/AC motif, (3) GC/AG and CT/GC motif, (4) AT/AC and GT/AT motif. -1 means no output for that motif} @@ -546,7 +640,7 @@ \optLine{insertion extension penalty per base (in addition to scoreInsOpen)} \optName{scoreStitchSJshift} \optValue{1} - \optLine{maximum score reduction while searching for SJ boundaries inthe stitching step} + \optLine{maximum score reduction while searching for SJ boundaries in the stitching step} \end{optTable} \optSection{Alignments and Seeding}\label{Alignments_and_Seeding} \begin{optTable} @@ -558,7 +652,7 @@ \optLine{real: seedSearchStartLmax normalized to read length (sum of mates' lengths for paired-end reads)} \optName{seedSearchLmax} \optValue{0} - \optLine{int{\textgreater}=0: defines the maximum length of the seeds, if =0 max seed lengthis infinite} + \optLine{int{\textgreater}=0: defines the maximum length of the seeds, if =0 seed length is not limited} \optName{seedMultimapNmax} \optValue{10000} \optLine{int{\textgreater}0: only pieces that map fewer than this value are utilized in the stitching procedure} @@ -574,6 +668,9 @@ \optName{seedSplitMin} \optValue{12} \optLine{int{\textgreater}0: min length of the seed sequences split by Ns or mate gap} +\optName{seedMapMin} + \optValue{5} + \optLine{int{\textgreater}0: min length of seeds to be mapped} \optName{alignIntronMin} \optValue{21} \optLine{minimum intron size: genomic gap is considered intron if its length{\textgreater}=alignIntronMin, otherwise it is considered Deletion} @@ -680,7 +777,7 @@ \optOpt{Junctions} \optOptLine{Chimeric.out.junction} \optOpt{SeparateSAMold} \optOptLine{output old SAM into separate Chimeric.out.sam file} \optOpt{WithinBAM} \optOptLine{output into main aligned BAM files (Aligned.*.bam)} - \optOpt{WithinBAM HardClip} \optOptLine{(default) hard-clipping in the CIGAR for supplemental chimeric alignments (defaultif no 2nd word is present)} + \optOpt{WithinBAM HardClip} \optOptLine{(default) hard-clipping in the CIGAR for supplemental chimeric alignments (default if no 2nd word is present)} \optOpt{WithinBAM SoftClip} \optOptLine{soft-clipping in the CIGAR for supplemental chimeric alignments} \end{optOptTable} \optName{chimSegmentMin} @@ -725,13 +822,13 @@ \optLine{int{\textgreater}=0: the score range for multi-mapping chimeras below the best chimeric score. Only works with --chimMultimapNmax {\textgreater} 1} \optName{chimNonchimScoreDropMin} \optValue{20} - \optLine{int{\textgreater}=0: to trigger chimeric detection, the drop in the best non-chimeric alignment score with respect to the read length has to be smaller than this value} + \optLine{int{\textgreater}=0: to trigger chimeric detection, the drop in the best non-chimeric alignment score with respect to the read length has to be greater than this value} \optName{chimOutJunctionFormat} \optValue{0} \optLine{int: formatting type for the Chimeric.out.junction file} \begin{optOptTable} \optOpt{0} \optOptLine{no comment lines/headers} - \optOpt{1} \optOptLine{comment lines at the end of the file: command line and Nreads: total, unique, multi} + \optOpt{1} \optOptLine{comment lines at the end of the file: command line and Nreads: total, unique/multi-mapping} \end{optOptTable} \end{optTable} \optSection{Quantification of Annotations}\label{Quantification_of_Annotations} @@ -778,7 +875,7 @@ \begin{optTable} \optName{waspOutputMode} \optValue{None} - \optLine{string: WASP allele-specific output type. This is re-implemenation of the original WASP mappability filtering by Bryce van de Geijn, Graham McVicker, Yoav Gilad {\&} Jonathan K Pritchard. Please cite the original WASP paper: Nature Methods 12, 1061–1063 (2015), https://www.nature.com/articles/nmeth.3582 .} + \optLine{string: WASP allele-specific output type. This is re-implementation of the original WASP mappability filtering by Bryce van de Geijn, Graham McVicker, Yoav Gilad {\&} Jonathan K Pritchard. Please cite the original WASP paper: Nature Methods 12, 1061–1063 (2015), https://www.nature.com/articles/nmeth.3582 .} \begin{optOptTable} \optOpt{SAMtag} \optOptLine{add WASP tags to the alignments that pass WASP filtering} \end{optOptTable} @@ -789,11 +886,17 @@ \optValue{None} \optLine{string(s): type of single-cell RNA-seq} \begin{optOptTable} - \optOpt{Droplet} \optOptLine{one cell barcode and one UMI barcode in read2, e.g. Drop-seq and 10X Chromium} + \optOpt{CB{\textunderscore}UMI{\textunderscore}Simple} \optOptLine{(a.k.a. Droplet) one UMI and one Cell Barcode of fixed length in read2, e.g. Drop-seq and 10X Chromium.} + \optOpt{CB{\textunderscore}UMI{\textunderscore}Complex} \optOptLine{multiple Cell Barcodes of varying length, one UMI of fixed length and one adapter sequence of fixed length are allowed in read2 only (e.g. inDrop, ddSeq).} + \optOpt{CB{\textunderscore}samTagOut} \optOptLine{output Cell Barcode as CR and/or CB SAm tag. No UMI counting. --readFilesIn cDNA{\textunderscore}read1 [cDNA{\textunderscore}read2 if paired-end] CellBarcode{\textunderscore}read . Requires --outSAMtype BAM Unsorted [and/or SortedByCoordinate]} + \optOpt{SmartSeq} \optOptLine{Smart-seq: each cell in a separate FASTQ (paired- or single-end), barcodes are corresponding read-groups, no UMI sequences, alignments deduplicated according to alignment start and end (after extending soft-clipped bases)} \end{optOptTable} \optName{soloCBwhitelist} \optValue{-} - \optLine{string: file with whitelist of cell barcodes} + \optLine{string(s): file(s) with whitelist(s) of cell barcodes. Only --soloType CB{\textunderscore}UMI{\textunderscore}Complex allows more than one whitelist file.} +\begin{optOptTable} + \optOpt{None} \optOptLine{no whitelist: all cell barcodes are allowed} +\end{optOptTable} \optName{soloCBstart} \optValue{1} \optLine{int{\textgreater}0: cell barcode start base} @@ -813,6 +916,59 @@ \optOpt{1} \optOptLine{equal to sum of soloCBlen+soloUMIlen} \optOpt{0} \optOptLine{not defined, do not check} \end{optOptTable} +\optName{soloBarcodeMate} + \optValue{0} + \optLine{int: identifies which read mate contains the barcode (CB+UMI) sequence} +\begin{optOptTable} + \optOpt{0} \optOptLine{barcode sequence is on separate read, which should always be the last file in the --readFilesIn listed} + \optOpt{1} \optOptLine{barcode sequence is a part of mate 1} + \optOpt{2} \optOptLine{barcode sequence is a part of mate 2} +\end{optOptTable} +\optName{soloCBposition} + \optValue{-} + \optLine{strings(s) position of Cell Barcode(s) on the barcode read.} + \optLine{Presently only works with --soloType CB{\textunderscore}UMI{\textunderscore}Complex, and barcodes are assumed to be on Read2.} + \optLine{Format for each barcode: startAnchor{\textunderscore}startPosition{\textunderscore}endAnchor{\textunderscore}endPosition} + \optLine{start(end)Anchor defines the Anchor Base for the CB: 0: read start; 1: read end; 2: adapter start; 3: adapter end} + \optLine{start(end)Position is the 0-based position with of the CB start(end) with respect to the Anchor Base} + \optLine{String for different barcodes are separated by space.} + \optLine{Example: inDrop (Zilionis et al, Nat. Protocols, 2017):} + \optLine{--soloCBposition 0{\textunderscore}0{\textunderscore}2{\textunderscore}-1 3{\textunderscore}1{\textunderscore}3{\textunderscore}8} +\optName{soloUMIposition} + \optValue{-} + \optLine{string position of the UMI on the barcode read, same as soloCBposition} + \optLine{Example: inDrop (Zilionis et al, Nat. Protocols, 2017):} + \optLine{--soloCBposition 3{\textunderscore}9{\textunderscore}3{\textunderscore}14} +\optName{soloAdapterSequence} + \optValue{-} + \optLine{string: adapter sequence to anchor barcodes. Only one adapter sequence is allowed.} +\optName{soloAdapterMismatchesNmax} + \optValue{1} + \optLine{int{\textgreater}0: maximum number of mismatches allowed in adapter sequence.} +\optName{soloCBmatchWLtype} + \optValue{1MM{\textunderscore}multi} + \optLine{string: matching the Cell Barcodes to the WhiteList} +\begin{optOptTable} + \optOpt{Exact} \optOptLine{only exact matches allowed} + \optOpt{1MM} \optOptLine{only one match in whitelist with 1 mismatched base allowed. Allowed CBs have to have at least one read with exact match.} + \optOpt{1MM{\textunderscore}multi} \optOptLine{multiple matches in whitelist with 1 mismatched base allowed, posterior probability calculation is used choose one of the matches.} +\end{optOptTable} + \optLine{Allowed CBs have to have at least one read with exact match. This option matches best with CellRanger 2.2.0} +\begin{optOptTable} + \optOpt{1MM{\textunderscore}multi{\textunderscore}pseudocounts} \optOptLine{same as 1MM{\textunderscore}Multi, but pseudocounts of 1 are added to all whitelist barcodes.} + \optOpt{1MM{\textunderscore}multi{\textunderscore}Nbase{\textunderscore}pseudocounts} \optOptLine{same as 1MM{\textunderscore}multi{\textunderscore}pseudocounts, multimatching to WL is allowed for CBs with N-bases. This option matches best with CellRanger {\textgreater}= 3.0.0} + \optOpt{ParseBio{\textunderscore}ED3} \optOptLine{allow up to edit distance of 3 fpr each of the barcodes. May include one deletion + one insertion. Only works with --soloType CB{\textunderscore}UMI{\textunderscore}Complex. Matches to multiple passlist barcdoes are not allowed. Similar to ParseBio Split-seq pipeline.} +\end{optOptTable} +\optName{soloInputSAMattrBarcodeSeq} + \optValue{-} + \optLine{string(s): when inputting reads from a SAM file (--readsFileType SAM SE/PE), these SAM attributes mark the barcode sequence (in proper order).} + \optLine{For instance, for 10X CellRanger or STARsolo BAMs, use --soloInputSAMattrBarcodeSeq CR UR .} + \optLine{This parameter is required when running STARsolo with input from SAM. } +\optName{soloInputSAMattrBarcodeQual} + \optValue{-} + \optLine{string(s): when inputting reads from a SAM file (--readsFileType SAM SE/PE), these SAM attributes mark the barcode qualities (in proper order).} + \optLine{For instance, for 10X CellRanger or STARsolo BAMs, use --soloInputSAMattrBarcodeQual CY UY .} + \optLine{If this parameter is '-' (default), the quality 'H' will be assigned to all bases.} \optName{soloStrand} \optValue{Forward} \optLine{string: strandedness of the solo libraries:} @@ -823,29 +979,65 @@ \end{optOptTable} \optName{soloFeatures} \optValue{Gene} - \optLine{string(s): genomic features for which the UMI counts per Cell Barcode are collected} + \optLine{string(s): genomic features for which the UMI counts per Cell Barcode are collected} \begin{optOptTable} \optOpt{Gene} \optOptLine{genes: reads match the gene transcript} \optOpt{SJ} \optOptLine{splice junctions: reported in SJ.out.tab} - \optOpt{GeneFull} \optOptLine{full genes: count all reads overlapping genes' exons and introns} + \optOpt{GeneFull} \optOptLine{full gene (pre-mRNA): count all reads overlapping genes' exons and introns} + \optOpt{GeneFull{\textunderscore}ExonOverIntron} \optOptLine{full gene (pre-mRNA): count all reads overlapping genes' exons and introns: prioritize 100% overlap with exons} + \optOpt{GeneFull{\textunderscore}Ex50pAS} \optOptLine{full gene (pre-RNA): count all reads overlapping genes' exons and introns: prioritize {\textgreater}50% overlap with exons. Do not count reads with 100% exonic overlap in the antisense direction.} +\end{optOptTable} +\optName{soloMultiMappers} + \optValue{Unique} + \optLine{string(s): counting method for reads mapping to multiple genes } +\begin{optOptTable} + \optOpt{Unique} \optOptLine{count only reads that map to unique genes} + \optOpt{Uniform} \optOptLine{uniformly distribute multi-genic UMIs to all genes} + \optOpt{Rescue} \optOptLine{distribute UMIs proportionally to unique+uniform counts (~ first iteration of EM)} + \optOpt{PropUnique} \optOptLine{distribute UMIs proportionally to unique mappers, if present, and uniformly if not.} + \optOpt{EM} \optOptLine{multi-gene UMIs are distributed using Expectation Maximization algorithm} \end{optOptTable} \optName{soloUMIdedup} \optValue{1MM{\textunderscore}All} \optLine{string(s): type of UMI deduplication (collapsing) algorithm} \begin{optOptTable} - \optOpt{1MM{\textunderscore}All} \optOptLine{all UMIs with 1 mismatch distance to each other are collapsed (i.e. counted once)} - \optOpt{1MM{\textunderscore}Directional} \optOptLine{follows the "directional" method from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017).} - \optOpt{1MM{\textunderscore}NotCollapsed} \optOptLine{UMIs with 1 mismatch distance to others are not collapsed (i.e. all counted)} + \optOpt{1MM{\textunderscore}All} \optOptLine{all UMIs with 1 mismatch distance to each other are collapsed (i.e. counted once).} + \optOpt{1MM{\textunderscore}Directional{\textunderscore}UMItools} \optOptLine{follows the "directional" method from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017).} + \optOpt{1MM{\textunderscore}Directional} \optOptLine{same as 1MM{\textunderscore}Directional{\textunderscore}UMItools, but with more stringent criteria for duplicate UMIs} + \optOpt{Exact} \optOptLine{only exactly matching UMIs are collapsed.} + \optOpt{NoDedup} \optOptLine{no deduplication of UMIs, count all reads.} + \optOpt{1MM{\textunderscore}CR} \optOptLine{CellRanger2-4 algorithm for 1MM UMI collapsing.} \end{optOptTable} +\optName{soloUMIfiltering} + \optValue{-} + \optLine{string(s) type of UMI filtering (for reads uniquely mapping to genes)} +\begin{optOptTable} + \optOpt{-} \optOptLine{basic filtering: remove UMIs with N and homopolymers (similar to CellRanger 2.2.0).} + \optOpt{MultiGeneUMI} \optOptLine{basic + remove lower-count UMIs that map to more than one gene.} + \optOpt{MultiGeneUMI{\textunderscore}All} \optOptLine{basic + remove all UMIs that map to more than one gene.} + \optOpt{MultiGeneUMI{\textunderscore}CR} \optOptLine{basic + remove lower-count UMIs that map to more than one gene, matching CellRanger {\textgreater} 3.0.0 .} +\end{optOptTable} + \optLine{Only works with --soloUMIdedup 1MM{\textunderscore}CR} \optName{soloOutFileNames} - \optValue{Solo.out/ genes.tsv barcodes.tsv matrix.mtx matrixSJ.mtx matrixGeneFull.mtx} - \optLine{string(s) file names for STARsolo output} + \optValue{Solo.out/ features.tsv barcodes.tsv matrix.mtx} + \optLine{string(s) file names for STARsolo output:} + \optLine{file{\textunderscore}name{\textunderscore}prefix gene{\textunderscore}names barcode{\textunderscore}sequences cell{\textunderscore}feature{\textunderscore}count{\textunderscore}matrix} +\optName{soloCellFilter} + \optValue{CellRanger2.2 3000 0.99 10} + \optLine{string(s): cell filtering type and parameters} +\begin{optOptTable} + \optOpt{None} \optOptLine{do not output filtered cells} + \optOpt{TopCells} \optOptLine{only report top cells by UMI count, followed by the exact number of cells} + \optOpt{CellRanger2.2} \optOptLine{simple filtering of CellRanger 2.2.} +\end{optOptTable} + \optLine{Can be followed by numbers: number of expected cells, robust maximum percentile for UMI count, maximum to minimum ratio for UMI count} + \optLine{The harcoded values are from CellRanger: nExpectedCells=3000; maxPercentile=0.99; maxMinRatio=10} \begin{optOptTable} - \optOpt{1st word} \optOptLine{file name prefix} - \optOpt{2nd word} \optOptLine{gene IDs and names} - \optOpt{3rd word} \optOptLine{barcode sequences} - \optOpt{4th word} \optOptLine{cell/Gene counts matrix} - \optOpt{5th word} \optOptLine{cell/SJ counts matrix} - \optOpt{6th word} \optOptLine{cell/GeneFull counts matrix} + \optOpt{EmptyDrops{\textunderscore}CR} \optOptLine{EmptyDrops filtering in CellRanger flavor. Please cite the original EmptyDrops paper: A.T.L Lun et al, Genome Biology, 20, 63 (2019): https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1662-y} \end{optOptTable} + \optLine{Can be followed by 10 numeric parameters: nExpectedCells maxPercentile maxMinRatio indMin indMax umiMin umiMinFracMedian candMaxN FDR simN } + \optLine{The harcoded values are from CellRanger: 3000 0.99 10 45000 90000 500 0.01 20000 0.01 10000} +\optName{soloOutFormatFeaturesGeneField3} + \optValue{"Gene Expression"} + \optLine{string(s): field 3 in the Gene features.tsv file. If "-", then no 3rd field is output.} \end{optTable} diff --git a/extras/docker/Dockerfile b/extras/docker/Dockerfile index b0101a62..5beb6493 100755 --- a/extras/docker/Dockerfile +++ b/extras/docker/Dockerfile @@ -1,8 +1,8 @@ -FROM debian:stretch-slim +FROM debian:stable-slim MAINTAINER dobin@cshl.edu -ARG STAR_VERSION=2.7.2a +ARG STAR_VERSION=2.7.9a ENV PACKAGES gcc g++ make wget zlib1g-dev unzip @@ -11,6 +11,7 @@ RUN set -ex RUN apt-get update && \ apt-get install -y --no-install-recommends ${PACKAGES} && \ apt-get clean && \ + g++ --version && \ cd /home && \ wget --no-check-certificate https://github.com/alexdobin/STAR/archive/${STAR_VERSION}.zip && \ unzip ${STAR_VERSION}.zip && \ diff --git a/extras/scripts/calcUMIperCell.awk b/extras/scripts/calcUMIperCell.awk new file mode 100644 index 00000000..c9915997 --- /dev/null +++ b/extras/scripts/calcUMIperCell.awk @@ -0,0 +1,27 @@ +# usage: awk -f calcUMIperCell.awk raw/matrix.mtx raw/barcodes.tsv filtered/barcodes.tsv | sort -k1,1rn > UMIperCell.txt +# output: column1 = total UMIs per cell +# column2 = 1 for cell that passed filtering, 0 otherwise + +BEGIN { + OFS="\t"; +} + +{ +if (ARGIND==1) { + if (FNR<4) + next; #skip header + + umiCount[$2]+=$3; + +} else if (ARGIND==2) { + rawCB[$1]=FNR; +} else if (ARGIND==3) { + filtCB[rawCB[$1]]=FNR; +} + +} + +END { + for (ii in umiCount) + print umiCount[ii], (ii in filtCB); +} diff --git a/extras/scripts/sjBED12.awk b/extras/scripts/sjBED12.awk new file mode 100644 index 00000000..460d10c3 --- /dev/null +++ b/extras/scripts/sjBED12.awk @@ -0,0 +1,47 @@ +# for SJs (e.g.converts 3-column BED into BED12 +# awk -v blockLen=10 -f ... sjIn.bed + +BEGIN { + OFS="\t"; + +} + +{ + if ($1=="") + next; + #################### input + chrom=$1; + chromStart1=$2; + chromEnd1=$3; + name="sj-" NR; + if (name=="") + name="."; + + score=1000; + + strand = $6; + if (strand!="+" && strand!="-") + strand="."; + + itemRgb="180,0,0"; + + #################### BED12 + chromStart = chromStart1-blockLen; + chromEnd = chromEnd1+blockLen; + thickStart = chromStart; + thickEnd = chromEnd; + blockCount = 2; + blockSizes = blockLen "," blockLen; + blockStarts = 0 "," chromEnd1-chromStart; + + print chrom, chromStart, chromEnd, name, score, strand, thickStart, thickEnd, itemRgb, blockCount, blockSizes, blockStarts > FILENAME ".bed12"; + + ####### GTF + source = "STAR_SJ"; + feature = "exon"; + frame = "."; + group = "transcript_id \"" name "\"; gene_id \"" name "\";" + + print chrom, source, feature, chromStart1-blockLen+1, chromStart1, score, strand, frame, group > FILENAME ".gtf"; + print chrom, source, feature, chromEnd1+1, chromEnd1+blockLen, score, strand, frame, group > FILENAME ".gtf"; +} diff --git a/extras/scripts/soloBasicCellFilter.awk b/extras/scripts/soloBasicCellFilter.awk index ac5debdc..c10c65a5 100644 --- a/extras/scripts/soloBasicCellFilter.awk +++ b/extras/scripts/soloBasicCellFilter.awk @@ -1,5 +1,4 @@ # usage awk -v exactCells=... -v maxCells=... -v maxPercentile=... -v maxMinRatio=... -f soloBasicCellFilter.awk -BEGIN { # default values - if variables were not defined by the user if (exactCells==0) exactCells=0; diff --git a/extras/scripts/soloCountMatrixFromBAM.awk b/extras/scripts/soloCountMatrixFromBAM.awk new file mode 100644 index 00000000..45cff818 --- /dev/null +++ b/extras/scripts/soloCountMatrixFromBAM.awk @@ -0,0 +1,70 @@ +# usage: +# samtools view Aligned.sortedByCoord.out.bam | awk -v fileWL=Solo.out/Gene/raw/barcodes.tsv -v fileGenes=Solo.out/Gene/raw/features.tsv \ +# soloCountMatrixFromBAM.awk | sort -k2,2n -k1,1n > matrix.mtx + + +function getTag(tag) +{ + tagOut=$0; + if (gsub(".*" tag,"",tagOut)==0) + return 0; + gsub("\t.*","",tagOut); + return tagOut; +} + +BEGIN { + + stderr="/dev/stderr"; + + ii=0; + while (getline < fileWL) { + ii++; + WL[$1]=ii; + }; + #print length(WL) > stderr; + + #getline < fileGenes; #skip header + ii=0; + while (getline < fileGenes) { + ii++; + geneID[$1]=ii; + }; + #print length(geneID) > stderr; +} + +{ + #if ((NR%1000000)==0) printf NR/1000000 " "$3 " " nTot+0 " " > "/dev/stderr"; + + GX=getTag("GX:Z:"); + if (GX=="0" || GX=="-") + next; + + CB=getTag("CB:Z:"); + if (CB=="0" || CB=="-") + next; + + UB=getTag("UB:Z:"); + if (UB=="0" || UB=="-") + next; + + # this is needed for CR + #if (substr(CB,length(CB)-1,1)=="-") + # CB=substr(CB,1, length(CB)-2); + + + cb=WL[CB]; + ge=geneID[GX]; + + + nTot++; + U[cb][ge][UB]++; + +} + +END { + for (cb in U) { + for (ge in U[cb]) { + print ge,cb,length(U[cb][ge]); + } + } +} diff --git a/extras/scripts/tagXSstrandedData.awk b/extras/scripts/tagXSstrandedData.awk index e4097805..05c63fe0 100644 --- a/extras/scripts/tagXSstrandedData.awk +++ b/extras/scripts/tagXSstrandedData.awk @@ -1,3 +1,9 @@ +# usage: +# cat Aligned.out.sam | awk -v strType=2 -f tagXSstrandedData.awk +# strType defines strandedness of the libraries: strType = mate whose strand is the same as RNA strand. +# For instance, for Illumina Tru-seq, strType=2 - the 2nd mate's strand is the same as RNA. + + BEGIN { OFS="\t"; strSym[0]="+"; diff --git a/source/AlignVsTranscript.h b/source/AlignVsTranscript.h new file mode 100644 index 00000000..bf81aba7 --- /dev/null +++ b/source/AlignVsTranscript.h @@ -0,0 +1,9 @@ +#ifndef H_AlignVsTranscript +#define H_AlignVsTranscript + +namespace AlignVsTranscript +{ + enum {Intron=0, ExonIntron=1, ExonIntronSpan=2, Concordant=3, N=4}; +}; + +#endif \ No newline at end of file diff --git a/source/BAMbinSortByCoordinate.cpp b/source/BAMbinSortByCoordinate.cpp index 359d90ee..f9cda44e 100644 --- a/source/BAMbinSortByCoordinate.cpp +++ b/source/BAMbinSortByCoordinate.cpp @@ -2,8 +2,9 @@ #include "ErrorWarning.h" #include "serviceFuns.cpp" #include "BAMfunctions.h" +#include "SequenceFuns.h" -void BAMbinSortByCoordinate(uint32 iBin, uint binN, uint binS, uint nThreads, string dirBAMsort, Parameters &P, Genome &mapGen) { +void BAMbinSortByCoordinate(uint32 iBin, uint binN, uint binS, uint nThreads, string dirBAMsort, Parameters &P, Genome &genome, Solo &solo) { if (binS==0) return; //nothing to do for empty bins //allocate arrays @@ -59,11 +60,17 @@ void BAMbinSortByCoordinate(uint32 iBin, uint binN, uint binS, uint nThreads, st exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); }; - outBAMwriteHeader(bgzfBin,P.samHeaderSortedCoord,mapGen.chrNameAll,mapGen.chrLengthAll); + outBAMwriteHeader(bgzfBin,P.samHeaderSortedCoord,genome.chrNameAll,genome.chrLengthAll); //send ordered aligns to bgzf one-by-one + char bam1[BAM_ATTR_MaxSize];//temp array for (uint ia=0;iaaddBAMtags(bam0,size0,bam1); + + bgzf_write(bgzfBin, bam0, size0); }; bgzf_flush(bgzfBin); @@ -71,4 +78,4 @@ void BAMbinSortByCoordinate(uint32 iBin, uint binN, uint binS, uint nThreads, st //release memory delete [] bamIn; delete [] startPos; -}; \ No newline at end of file +}; diff --git a/source/BAMbinSortByCoordinate.h b/source/BAMbinSortByCoordinate.h index a256b696..cbf03c68 100644 --- a/source/BAMbinSortByCoordinate.h +++ b/source/BAMbinSortByCoordinate.h @@ -3,9 +3,10 @@ #include "IncludeDefine.h" #include "Parameters.h" #include "Genome.h" +#include "Solo.h" #include SAMTOOLS_BGZF_H -void BAMbinSortByCoordinate(uint32 iBin, uint binN, uint binS, uint nThreads, string dirBAMsort, Parameters &P, Genome &mapGen); +void BAMbinSortByCoordinate(uint32 iBin, uint binN, uint binS, uint nThreads, string dirBAMsort, Parameters &P, Genome &mapGen, Solo &solo); #endif \ No newline at end of file diff --git a/source/BAMbinSortUnmapped.cpp b/source/BAMbinSortUnmapped.cpp index 8ff9fe41..0cacb4a7 100644 --- a/source/BAMbinSortUnmapped.cpp +++ b/source/BAMbinSortUnmapped.cpp @@ -2,7 +2,7 @@ #include "ErrorWarning.h" #include "BAMfunctions.h" -void BAMbinSortUnmapped(uint32 iBin, uint nThreads, string dirBAMsort, Parameters &P, Genome &mapGen) { +void BAMbinSortUnmapped(uint32 iBin, uint nThreads, string dirBAMsort, Parameters &P, Genome &genome, Solo &solo) { BGZF *bgzfBin; bgzfBin=bgzf_open((dirBAMsort+"/b"+to_string((uint) iBin)).c_str(),("w"+to_string((long long) P.outBAMcompression)).c_str()); @@ -13,7 +13,7 @@ void BAMbinSortUnmapped(uint32 iBin, uint nThreads, string dirBAMsort, Parameter exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); }; - outBAMwriteHeader(bgzfBin,P.samHeaderSortedCoord,mapGen.chrNameAll,mapGen.chrLengthAll); + outBAMwriteHeader(bgzfBin,P.samHeaderSortedCoord,genome.chrNameAll,genome.chrLengthAll); vector bamInFile; @@ -37,24 +37,35 @@ void BAMbinSortUnmapped(uint32 iBin, uint nThreads, string dirBAMsort, Parameter bamInStream[it].read(bamIn[it],sizeof(int32));//read BAM record size if (bamInStream[it].good()) { bamSize[it]=((*(uint32*)bamIn[it])+sizeof(int32));//true record size +=4 (4 bytes for uint-iRead) - bamInStream[it].read(bamIn[it]+sizeof(int32),bamSize.at(it)-sizeof(int32)+sizeof(uint));//read the rest of the record, including last uint = iRead - startPos[*(uint*)(bamIn[it]+bamSize.at(it))]=it;//startPos[iRead]=it : record the order of the files to output + bamInStream[it].read(bamIn[it]+sizeof(int32),bamSize.at(it)-sizeof(int32)+sizeof(uint64));//read the rest of the record, including last uint = iRead + uint64 iRead=*(uint*)(bamIn[it]+bamSize.at(it)); + iRead = iRead >> 32; //iRead is recorded in top 32bits + startPos[iRead]=it;//startPos[iRead]=it : record the order of the files to output } else {//nothing to do here, file is empty, do not record it }; }; //send ordered aligns to bgzf one-by-one + char bam1[BAM_ATTR_MaxSize];//temp array while (startPos.size()>0) { uint it=startPos.begin()->second; uint startNext=startPos.size()>1 ? (++startPos.begin())->first : (uint) -1; while (true) { - bgzf_write(bgzfBin, bamIn[it], bamSize.at(it)); + //add extra tags to the BAM record + char* bam0=bamIn[it]; + uint32 size0=bamSize.at(it); + + if (solo.pSolo.samAttrYes) + solo.soloFeat[solo.pSolo.featureInd[solo.pSolo.samAttrFeature]]->addBAMtags(bam0,size0,bam1); + + bgzf_write(bgzfBin, bam0, size0); bamInStream[it].read(bamIn[it],sizeof(int32));//read record size if (bamInStream[it].good()) { bamSize[it]=((*(uint32*)bamIn[it])+sizeof(int32)); - bamInStream[it].read(bamIn[it]+sizeof(int32),bamSize.at(it)-sizeof(int32)+sizeof(uint));//read the rest of the record, including la$ - uint iRead=*(uint*)(bamIn[it]+bamSize.at(it)); + bamInStream[it].read(bamIn[it]+sizeof(int32),bamSize.at(it)-sizeof(int32)+sizeof(uint));//read the rest of the record, including + uint64 iRead=*(uint*)(bamIn[it]+bamSize.at(it)); + iRead = iRead >> 32; //iRead is recorded in top 32bits if (iRead>startNext) {//this read from this chunk is > than a read from another chunk startPos[iRead]=it; break; diff --git a/source/BAMbinSortUnmapped.h b/source/BAMbinSortUnmapped.h index 8167df79..4a12ebfd 100644 --- a/source/BAMbinSortUnmapped.h +++ b/source/BAMbinSortUnmapped.h @@ -3,9 +3,10 @@ #include "IncludeDefine.h" #include "Parameters.h" #include "Genome.h" +#include "Solo.h" #include SAMTOOLS_BGZF_H -void BAMbinSortUnmapped(uint32 iBin, uint nThreads, string dirBAMsort, Parameters &P, Genome &mapGen); +void BAMbinSortUnmapped(uint32 iBin, uint nThreads, string dirBAMsort, Parameters &P, Genome &genome, Solo &solo); #endif diff --git a/source/BAMfunctions.cpp b/source/BAMfunctions.cpp index 75e05694..af6ce237 100644 --- a/source/BAMfunctions.cpp +++ b/source/BAMfunctions.cpp @@ -1,6 +1,7 @@ #include "BAMfunctions.h" #include "htslib/htslib/kstring.h" + string bam_cigarString (bam1_t *b) {//output CIGAR string // kstring_t strK; // kstring_t *str=&strK; @@ -59,9 +60,10 @@ int bam_read1_fromArray(char *bamChar, bam1_t *b) //modified from samtools bam_r if (b->m_data < b->l_data) { b->m_data = b->l_data; kroundup32(b->m_data); - b->data = (uint8_t*)realloc(b->data, b->m_data); - if (!b->data) - return -4; +// no need to realloc b->data, because it is overwritten later with bamChar +// b->data = (uint8_t*)realloc(b->data, b->m_data); +// if (!b->data) +// return -4; } // // if (bgzf_read(fp, b->data, b->l_data) != b->l_data) return -4; // // //b->l_aux = b->l_data - c->n_cigar * 4 - c->l_qname - c->l_qseq - (c->l_qseq+1)/2; @@ -89,22 +91,104 @@ void outBAMwriteHeader (BGZF* fp, const string &samh, const vector &chr bgzf_flush(fp); }; -template -TintType bamAttributeInt(const char *bamAux, const char *attrName) {//not tested!!! - const char *attrStart=strstr(bamAux,attrName); - if (attrStart==NULL) return (TintType) -1; - switch (attrStart[2]) { - case ('c'): - return (TintType) *(int8_t*)(attrStart+3); - case ('s'): - return (TintType) *(int16_t*)(attrStart+3); - case ('i'): - return (TintType) *(int32_t*)(attrStart+3); - case ('C'): - return (TintType) *(uint8_t*)(attrStart+3); - case ('S'): - return (TintType) *(uint16_t*)(attrStart+3); - case ('I'): - return (TintType) *(uint32_t*)(attrStart+3); - }; +// calculate bin given an alignment covering [beg,end) (zero-based, half-close-half-open) +int reg2bin(int beg, int end) +{ + --end; + if (beg>>14 == end>>14) return ((1<<15)-1)/7 + (beg>>14); + if (beg>>17 == end>>17) return ((1<<12)-1)/7 + (beg>>17); + if (beg>>20 == end>>20) return ((1<<9)-1)/7 + (beg>>20); + if (beg>>23 == end>>23) return ((1<<6)-1)/7 + (beg>>23); + if (beg>>26 == end>>26) return ((1<<3)-1)/7 + (beg>>26); + return 0; +}; + +int bamAttrArrayWrite(int32 attr, const char* tagName, char* attrArray ) { + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + attrArray[2]='i'; + *( (int32*) (attrArray+3))=attr; + return 3+sizeof(int32); +}; +int bamAttrArrayWrite(float attr, const char* tagName, char* attrArray ) { + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + attrArray[2]='f'; + *( (float*) (attrArray+3))=attr; + return 3+sizeof(int32); +}; +int bamAttrArrayWrite(char attr, const char* tagName, char* attrArray ) { + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + attrArray[2]='A'; + attrArray[3]=attr; + return 3+sizeof(char); +}; +int bamAttrArrayWrite(string &attr, const char* tagName, char* attrArray ) { + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + attrArray[2]='Z'; + memcpy(attrArray+3,attr.c_str(),attr.size()+1);//copy string data including \0 + return 3+attr.size()+1; +}; +int bamAttrArrayWrite(const vector &attr, const char* tagName, char* attrArray ) { + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + attrArray[2]='B'; + attrArray[3]='c'; + *( (int32*) (attrArray+4))=attr.size(); + memcpy(attrArray+4+sizeof(int32),attr.data(),attr.size());//copy array data + return 4+sizeof(int32)+attr.size(); }; +int bamAttrArrayWrite(const vector &attr, const char* tagName, char* attrArray ) { + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + attrArray[2]='B'; + attrArray[3]='i'; + *( (int32*) (attrArray+4))=attr.size(); + memcpy(attrArray+4+sizeof(int32),attr.data(),sizeof(int32)*attr.size());//copy array data + return 4+sizeof(int32)+sizeof(int32)*attr.size(); +}; + +int bamAttrArrayWriteSAMtags(string &attrStr, char *attrArray, Parameters &P) {//write bam record into attrArray for string attribute attString + size_t pos1=0, pos2=0; + int nattr=0; + do {//cycle over multiple tags separated by tab + pos2 = attrStr.find('\t',pos1); + string attr1 = attrStr.substr(pos1, pos2-pos1); //substring containing one tag + pos1=pos2+1; //for the next search + + if (attr1.empty()) + continue; //extra tab at the beginning, or consecutive tabs + + uint16_t tagn = * ( (uint16_t*) attr1.c_str() ); + if ( !P.readFiles.samAttrKeepAll && P.readFiles.samAttrKeep.count(tagn)==0 ) + continue; //skip tags not contained the list + + switch (attr1.at(3)) {//TODO: support other tag types (vector tags) + case 'i': + { + int32 a1=stol(attr1.substr(5)); + nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); + break; + }; + case 'A': + { + char a1=attr1.at(5); + nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); + break; + }; + break; + case 'Z': + { + string a1=attr1.substr(5); + nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); + break; + }; + case 'f': + { + float a1=stof(attr1.substr(5)); + nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); + break; + }; + }; + } while (pos2 != string::npos); + + return nattr; +}; + + diff --git a/source/BAMfunctions.h b/source/BAMfunctions.h index 51f3dcc4..6f4dcae1 100644 --- a/source/BAMfunctions.h +++ b/source/BAMfunctions.h @@ -4,7 +4,76 @@ #include "IncludeDefine.h" #include SAMTOOLS_BGZF_H #include SAMTOOLS_SAM_H - void outBAMwriteHeader (BGZF* fp, const string &samh, const vector &chrn, const vector &chrl); - int bam_read1_fromArray(char *bamChar, bam1_t *b); - string bam_cigarString (bam1_t *b); +#include "ErrorWarning.h" + + +void outBAMwriteHeader (BGZF* fp, const string &samh, const vector &chrn, const vector &chrl); +int bam_read1_fromArray(char *bamChar, bam1_t *b); +string bam_cigarString (bam1_t *b); + +int reg2bin(int beg, int end); +int bamAttrArrayWrite(int32 attr, const char* tagName, char* attrArray ); +int bamAttrArrayWrite(float attr, const char* tagName, char* attrArray ); +int bamAttrArrayWrite(char attr, const char* tagName, char* attrArray ); +int bamAttrArrayWrite(string &attr, const char* tagName, char* attrArray ); +int bamAttrArrayWrite(const vector &attr, const char* tagName, char* attrArray ); +int bamAttrArrayWrite(const vector &attr, const char* tagName, char* attrArray ); +int bamAttrArrayWriteSAMtags(string &attrStr, char *attrArray, Parameters &P); + +template +TintType bamAttributeInt(const char *bamAux, const char *attrName) {//not tested!!! + const char *attrStart=strstr(bamAux,attrName); + if (attrStart==NULL) return (TintType) -1; + switch (attrStart[2]) { + case ('c'): + return (TintType) *(int8_t*)(attrStart+3); + case ('s'): + return (TintType) *(int16_t*)(attrStart+3); + case ('i'): + return (TintType) *(int32_t*)(attrStart+3); + case ('C'): + return (TintType) *(uint8_t*)(attrStart+3); + case ('S'): + return (TintType) *(uint16_t*)(attrStart+3); + case ('I'): + return (TintType) *(uint32_t*)(attrStart+3); + }; +}; + +template +int bamAttrArrayWriteInt(intType xIn, const char* tagName, char* attrArray, Parameters &P) {//adapted from samtools + attrArray[0]=tagName[0];attrArray[1]=tagName[1]; + #define ATTR_RECORD_INT(_intChar,_intType,_intValue) attrArray[2] = _intChar; *(_intType*)(attrArray+3) = (_intType) _intValue; return 3+sizeof(_intType) + int64 x = (int64) xIn; + if (x < 0) { + if (x >= -127) { + ATTR_RECORD_INT('c',int8_t,x); + } else if (x >= -32767) { + ATTR_RECORD_INT('s',int16_t,x); + } else { + ATTR_RECORD_INT('i',int32_t,x); + if (!(x>=-2147483647)) { + ostringstream errOut; + errOut <<"EXITING because of FATAL BUG: integer out of range for BAM conversion: "<< x <<"\n"; + errOut <<"SOLUTION: contact Alex Dobin at dobin@cshl.edu\n"; + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); + }; + }; + } else { + if (x <= 255) { + ATTR_RECORD_INT('C',uint8_t,x); + } else if (x <= 65535) { + ATTR_RECORD_INT('S',uint16_t,x); + } else { + ATTR_RECORD_INT('I',uint32_t,x); + if (!(x<=4294967295)) { + ostringstream errOut; + errOut <<"EXITING because of FATAL BUG: integer out of range for BAM conversion: "<< x <<"\n"; + errOut <<"SOLUTION: contact Alex Dobin at dobin@cshl.edu\n"; + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); + }; + }; + }; +}; + #endif \ No newline at end of file diff --git a/source/BAMoutput.cpp b/source/BAMoutput.cpp index a782d301..e61faa64 100644 --- a/source/BAMoutput.cpp +++ b/source/BAMoutput.cpp @@ -93,12 +93,6 @@ void BAMoutput::coordOneAlign (char *bamIn, uint bamSize, uint iRead) { }; }; -// if ( alignG == (uint32) -1 ) {//unmapped alignment, last bin -// iBin=nBins-1; -// } else { -// iBin=(alignG + chrStart)/binGlen; -// }; - //write buffer is filled if (binBytes[iBin]+bamSize+sizeof(uint) > ( (iBin>0 || nBins>1) ? binSize : binSize1) ) {//write out this buffer if ( nBins>1 || iBin==(P.outBAMcoordNbins-1) ) {//normal writing, bins have already been determined diff --git a/source/ChimericAlign.cpp b/source/ChimericAlign.cpp index 3038d9d9..8d3da5c6 100644 --- a/source/ChimericAlign.cpp +++ b/source/ChimericAlign.cpp @@ -1,7 +1,7 @@ #include "ChimericAlign.h" ChimericAlign::ChimericAlign(ChimericSegment &seg1in, ChimericSegment &seg2in, int chimScoreIn, Genome &genomeIn, ReadAlign *RAin) - : seg1(seg1in), seg2(seg2in),chimScore(chimScoreIn), P(seg1in.P), pCh(P.pCh), mapGen(genomeIn), RA(RAin) { + : seg1(seg1in), seg2(seg2in),chimScore(chimScoreIn), RA(RAin), P(seg1in.P), pCh(P.pCh), mapGen(genomeIn) { stitchingDone=false; al1=&seg1.align; diff --git a/source/ChimericAlign.h b/source/ChimericAlign.h index 5fa184a1..78239159 100644 --- a/source/ChimericAlign.h +++ b/source/ChimericAlign.h @@ -24,16 +24,17 @@ class ChimericAlign ChimericAlign(ChimericSegment &seg1in, ChimericSegment &seg2in, int chimScoreIn, Genome &genomeIn, ReadAlign *RAin); //allocate void chimericJunctionOutput(fstream &outStream, uint chimN, int maxNonChimAlignScore, bool PEmerged_flag, int chimScoreBest, int maxPossibleAlignScore); + static void chimericBAMoutput(Transcript *al1, Transcript *al2, ReadAlign *RA, const uint iTr, const uint chimN, const bool isBestChimAlign, const Parameters& P); void chimericStitching(char *genSeq, char **Read1); bool chimericCheck(); bool stitchingDone; + ReadAlign *RA; private: Parameters &P; ParametersChimeric &pCh; Genome &mapGen; - ReadAlign *RA; }; diff --git a/source/ChimericAlign_chimericBAMoutput.cpp b/source/ChimericAlign_chimericBAMoutput.cpp new file mode 100644 index 00000000..e41c0f0c --- /dev/null +++ b/source/ChimericAlign_chimericBAMoutput.cpp @@ -0,0 +1,105 @@ +#include "ChimericAlign.h" +#include "ReadAlign.h" +#include "BAMfunctions.h" + +#include + +void ChimericAlign::chimericBAMoutput(Transcript *al1, Transcript *al2, ReadAlign *RA, const uint iTr, const uint chimN, const bool isBestChimAlign, const Parameters& P) +{ + vector trChim(2); + trChim[0] = al1; + trChim[1] = al2; + + int chimRepresent=-999, chimType=0; + if (trChim[0]->exons[0][EX_iFrag]!=trChim[0]->exons[trChim[0]->nExons-1][EX_iFrag]) {//tr0 has both mates + chimRepresent = 0; + chimType = 1; + } else if (trChim[1]->exons[0][EX_iFrag]!=trChim[1]->exons[trChim[1]->nExons-1][EX_iFrag]) {//tr1 has both mates + chimRepresent = 1; + chimType = 1; + } else if (trChim[0]->exons[0][EX_iFrag]!=trChim[1]->exons[0][EX_iFrag]) {//tr0 and tr1 are single different mates + chimRepresent = -1; + chimType = 2; + } else {//two chimeric segments are on the same mate - this can only happen for single-end reads + chimRepresent = (trChim[0]->maxScore > trChim[1]->maxScore) ? 0 : 1; + chimType = 3; + }; + + int alignType, bamN=0, bamIsuppl=-1, bamIrepr=-1; + uint bamBytesTotal=0;//estimate of the total size of all bam records, for output buffering + uint mateChr,mateStart; + uint8_t mateStrand; + for (uint itr=0;itrprimaryFlag=isBestChimAlign; + if (chimType==2) {//PE, encompassing + mateChr=trChim[1-itr]->Chr; + mateStart=trChim[1-itr]->exons[0][EX_G]; + mateStrand=(uint8_t) (trChim[1-itr]->Str!=trChim[1-itr]->exons[0][EX_iFrag]); + alignType=-10; + } else {//spanning chimeric alignment, could be PE or SE + mateChr=-1;mateStart=-1;mateStrand=0;//no need fot mate info unless this is the supplementary alignment + if (chimRepresent==(int)itr) { + alignType=-10; //this is representative part of chimeric alignment, record is as normal; if encompassing chimeric junction, both are recorded as normal + bamIrepr=bamN; + if (trChim[itr]->exons[0][EX_iFrag]!=trChim[1-itr]->exons[0][EX_iFrag]) {//the next mate is chimerically split + ++bamIrepr; + }; +//TODO check flags of SE split read +// if (chimType==3) { +// bamIrepr=bamN; +// } else if (trChim[itr]->exons[0][EX_iFrag]==trChim[1-itr]->exons[0][EX_iFrag]) { +// +// }; +// bamIrepr=( (itr%2)==(trChim[itr]->Str) && chimType!=3) ? bamN+1 : bamN;//this is the mate that is chimerically split + } else {//"supplementary" chimeric segment + alignType=P.pCh.out.bamHardClip ? ( ( itr%2==trChim[itr]->Str ) ? -12 : -11) : -13 ; //right:left chimeric junction + bamIsuppl=bamN; + if (chimType==1) {//PE alignment, need mate info for the suppl + uint iex=0; + for (;iexnExons-1;iex++) { + if (trChim[chimRepresent]->exons[iex][EX_iFrag]!=trChim[itr]->exons[0][EX_iFrag]) { + break; + }; + }; + mateChr=trChim[chimRepresent]->Chr; + mateStart=trChim[chimRepresent]->exons[iex][EX_G]; + mateStrand=(uint8_t) (trChim[chimRepresent]->Str!=trChim[chimRepresent]->exons[iex][EX_iFrag]); + }; + }; + + }; + + bamN+=RA->alignBAM(*trChim[itr], chimN, iTr, RA->mapGen.chrStart[trChim[itr]->Chr], mateChr, \ + mateStart-RA->mapGen.chrStart[(mateChrmapGen.nChrReal ? mateChr : 0)], mateStrand, alignType, \ + NULL, P.outSAMattrOrder, RA->outBAMoneAlign+bamN, RA->outBAMoneAlignNbytes+bamN); + bamBytesTotal+=RA->outBAMoneAlignNbytes[0]+RA->outBAMoneAlignNbytes[1];//outBAMoneAlignNbytes[1] = 0 if SE is recorded + }; + + //write all bam lines + for (int ii=0; ii=0) { + bam1_t *b; + b=bam_init1(); + bam_read1_fromArray(RA->outBAMoneAlign[tagI], b); + uint8_t* auxp=bam_aux_get(b,"NM"); + uint32_t auxv=bam_aux2i(auxp); + string tagSA1="SAZ"+RA->mapGen.chrName[b->core.tid]+','+to_string((uint)b->core.pos+1) +',' + ( (b->core.flag&0x10)==0 ? '+':'-') + \ + ',' + bam_cigarString(b) + ',' + to_string((uint)b->core.qual) + ',' + to_string((uint)auxv) + ';' ; + + memcpy( (void*) (RA->outBAMoneAlign[ii]+RA->outBAMoneAlignNbytes[ii]), tagSA1.c_str(), tagSA1.size()+1);//copy string including \0 at the end + RA->outBAMoneAlignNbytes[ii]+=tagSA1.size()+1; + * ( (uint32*) RA->outBAMoneAlign[ii] ) = RA->outBAMoneAlignNbytes[ii]-sizeof(uint32); + free(b); // don't use bam_destroy1(), because bam_read1_fromArray does not allocate memory for b->data + }; + + if (P.outBAMunsorted) RA->outBAMunsorted->unsortedOneAlign(RA->outBAMoneAlign[ii], RA->outBAMoneAlignNbytes[ii], ii>0 ? 0 : bamBytesTotal); + if (P.outBAMcoord) RA->outBAMcoord->coordOneAlign(RA->outBAMoneAlign[ii], RA->outBAMoneAlignNbytes[ii], (RA->iReadAll<<32) ); + }; + +}; diff --git a/source/ChimericDetection.cpp b/source/ChimericDetection.cpp old mode 100644 new mode 100755 index 3d421acd..7a70c762 --- a/source/ChimericDetection.cpp +++ b/source/ChimericDetection.cpp @@ -3,4 +3,4 @@ ChimericDetection::ChimericDetection(Parameters &Pin, Transcript ***trAll, uint *nWinTr, char** Read1in, Genome &mapGenIn, fstream *ostreamChimJunctionIn, ReadAlign *RAin) : P(Pin), RA(RAin), trAll(trAll), nWinTr(nWinTr), Read1(Read1in), outGen(mapGenIn), ostreamChimJunction(ostreamChimJunctionIn) { -}; \ No newline at end of file +}; diff --git a/source/ChimericDetection.h b/source/ChimericDetection.h old mode 100644 new mode 100755 index 1dcf3794..12b5d1af --- a/source/ChimericDetection.h +++ b/source/ChimericDetection.h @@ -17,16 +17,12 @@ class ChimericDetection { uint nW, *nWinTr; char** Read1; Genome &outGen; - uint *readLength; public: - uint chimN; vector chimAligns; - bool chimRecord; - int chimScoreBest; ChimericDetection(Parameters &Pin, Transcript ***trAll, uint *nWinTr, char** Read1in, Genome &genomeIn, fstream *ostreamChimJunctionIn, ReadAlign *RA); - bool chimericDetectionMult(uint nWin, uint *readLengthIn, int maxNonChimAlignScore, bool PEmerged_flag); + bool chimericDetectionMult(uint nWin, uint *readLength, int maxNonChimAlignScore, ReadAlign *PEunmergedRA); fstream *ostreamChimJunction; }; diff --git a/source/ChimericDetection_chimericDetectionMult.cpp b/source/ChimericDetection_chimericDetectionMult.cpp index 1967d009..14f8b3a3 100644 --- a/source/ChimericDetection_chimericDetectionMult.cpp +++ b/source/ChimericDetection_chimericDetectionMult.cpp @@ -1,6 +1,7 @@ //#include "blocksOverlap.h" #include "ChimericDetection.h" #include "ChimericSegment.h" +#include "ReadAlign.h" int chimericAlignScore (ChimericSegment & seg1, ChimericSegment & seg2) { @@ -19,9 +20,7 @@ int chimericAlignScore (ChimericSegment & seg1, ChimericSegment & seg2) }; ///////////////////////////////////////////////////////////// -bool ChimericDetection::chimericDetectionMult(uint nW, uint *readLength, int maxNonChimAlignScore, bool PEmerged_flag) { - - chimRecord=false; +bool ChimericDetection::chimericDetectionMult(uint nW, uint *readLength, int maxNonChimAlignScore, ReadAlign *PEunmergedRA) { // for (uint ii=0;ii= minScoreToConsider) + minScoreToConsider = maxNonChimAlignScore + 1; + if ((maxPossibleAlignScore - P.pCh.scoreDropMax) > minScoreToConsider) + minScoreToConsider = maxPossibleAlignScore - P.pCh.scoreDropMax; for (uint iW1=0; iW1 maxNonChimAlignScore - && - chimScore >= maxPossibleAlignScore - P.pCh.scoreDropMax - && - chimScore >= P.pCh.scoreMin - && - chimScore>=chimScoreBest-(int)P.pCh.multimapScoreRange - ) - {//candidate chimera + if (chimScore >= minScoreToConsider) {//candidate chimera ChimericAlign chAl(seg1, seg2, chimScore, outGen, RA); if (!chAl.chimericCheck()) @@ -81,12 +78,22 @@ bool ChimericDetection::chimericDetectionMult(uint nW, uint *readLength, int max //re-calculated chimScoreBest includes non-canonical penalty, so the re-calculated score is lower, in some cases it goes to 0 if some checks are not passed chAl.chimericStitching(outGen.G, Read1); // rescore after stitching. - if (chAl.chimScore > maxNonChimAlignScore) { // survived stitching. + if (chAl.chimScore >= minScoreToConsider) { // survived stitching. chimAligns.push_back(chAl);//add this chimeric alignment - if (chimAligns.back().chimScore > chimScoreBest) + if (chimAligns.back().chimScore > chimScoreBest) { chimScoreBest=chimAligns.back().chimScore; - }; // endif stitched chimera survived. + bestChimAlign = chimAligns.size()-1; + if ((chimScoreBest - (int)P.pCh.multimapScoreRange) > minScoreToConsider) + // best score increased, so subsequent alignment candidates must score higher + minScoreToConsider = chimScoreBest - (int)P.pCh.multimapScoreRange; + }; + } // endif stitched chimera survived. + else { + // al1, al2 allocated during stitching + delete chAl.al1; + delete chAl.al2; + }; }; // endif meets chim score criteria };//cycle over window2 aligns @@ -95,39 +102,37 @@ bool ChimericDetection::chimericDetectionMult(uint nW, uint *readLength, int max };//cycle over window1 if (chimScoreBest==0) - return chimRecord; + return false; - chimN=0; + uint chimN=0; for (auto cAit=chimAligns.begin(); cAitchimScore >= chimScoreBest - (int)P.pCh.multimapScoreRange) + if (cAit->chimScore >= minScoreToConsider) ++chimN; }; - /* - if (chimN > 2*P.pCh.multimapNmax) //too many loci (considering 2* more candidates for stitching below) - return chimRecord; + if (chimN > P.pCh.multimapNmax) //too many loci + return false; - chimN=0; - for (auto cAit=chimAligns.begin(); cAitchimScore >= chimScoreBest-(int)P.pCh.multimapScoreRange) { - cAit->chimericStitching(outGen.G, Read1[0]); - if (cAit->chimScore >= chimScoreBest - (int)P.pCh.multimapScoreRange) - ++chimN; - }; - }; - */ + uint iTr = 0; //keep track of "HI" SAM attribute + for (std::size_t i = 0; i < chimAligns.size(); i++) {//output chimeras within score range + if (chimAligns[i].chimScore >= minScoreToConsider) { - if (chimN > P.pCh.multimapNmax) //too many loci - return chimRecord; + if (P.pCh.out.junctions) + chimAligns[i].chimericJunctionOutput(*ostreamChimJunction, chimN, maxNonChimAlignScore, PEunmergedRA != NULL, chimScoreBest, maxPossibleAlignScore); - for (auto cAit=chimAligns.begin(); cAitchimScore >= chimScoreBest-(int)P.pCh.multimapScoreRange) - cAit->chimericJunctionOutput(*ostreamChimJunction, chimN, maxNonChimAlignScore, PEmerged_flag, chimScoreBest, maxPossibleAlignScore); - }; + if (P.pCh.out.bam) { + // convert merged SE chimera to PE chimera if this is a merged chimera + if (PEunmergedRA != NULL) { + chimAligns[i].RA = PEunmergedRA; + chimAligns[i].RA->peOverlapChimericSEtoPE(chimAligns[i].al1, chimAligns[i].al2, chimAligns[i].al1, chimAligns[i].al2); + }; + chimAligns[i].chimericBAMoutput(chimAligns[i].al1, chimAligns[i].al2, chimAligns[i].RA, iTr, chimN, i == bestChimAlign, P); + }; + iTr++; - if (chimN>0) - chimRecord=true; + }; + }; - return chimRecord; + return chimN > 0; };//END diff --git a/source/ClipCR4.cpp b/source/ClipCR4.cpp new file mode 100644 index 00000000..0b43d919 --- /dev/null +++ b/source/ClipCR4.cpp @@ -0,0 +1,109 @@ +#include "ClipCR4.h" + +ClipCR4::ClipCR4() +{ + dbN = 64; + + scoreMatrix = { + 1, -2, -2, -2, -2, + -2, 1, -2, -2, -2, + -2, -2, 1, -2, -2, + -2, -2, -2, 1, -2, + -2, -2, -2, -2, 0 + }; + + readLen = 91; + alphabetLength = 5; + gapOpen = 2; + gapExt = 2; + + + dbSeqArr = new uint8_t[dbN*readLen]; + dbSeqs = new uint8_t*[dbN]; + for (int id=0; id= (int)ib*7) {//score>=0.7*clipL + ib1 = ib; + score1 = score; + }; + } else { + score -= 2; //-2 for mismatches + if ( ib-score > 27 ) + break; //score drop is too big + }; + }; + if ( score1<20 ) + ib1=0; //score is too small + + return ib1; +}; + + diff --git a/source/ClipCR4.h b/source/ClipCR4.h new file mode 100644 index 00000000..e4bd5b1c --- /dev/null +++ b/source/ClipCR4.h @@ -0,0 +1,41 @@ +#ifndef CODE_ClipCR4 +#define CODE_ClipCR4 + +#include "IncludeDefine.h" +#include "opal/opal.h" + +class ClipCR4 +{ +public: + int dbN;//number of sequence in the opal "database" + + vector storeClip; + + // Results for each sequence in database + vector opalRes; + + OpalSearchResult** opalResP; + + //constructor + ClipCR4(); + void opalFillOneSeq(uint32 idb, char *seq, uint32 seqL); + void opalAlign(uint8 *query, uint32 queryLen, int dbN1); + uint32 polyTail3p(char *seq, uint32 seqLen); + +private: + + uint32 readLen; //sequence length to align against + + int alphabetLength; + int gapOpen; + int gapExt; + vector scoreMatrix; + + // Database + uint8_t* dbSeqArr; + uint8_t** dbSeqs; + int* dbSeqsLen; + +}; + +#endif diff --git a/source/ClipMate.h b/source/ClipMate.h new file mode 100644 index 00000000..1e895609 --- /dev/null +++ b/source/ClipMate.h @@ -0,0 +1,34 @@ +#ifndef CODE_ClipMate +#define CODE_ClipMate + +#include "IncludeDefine.h" +#include "ClipCR4.h" + +class ClipMate +{ +public: + //clip parameters + int type; //standard sequence clip: 0=5p, 1=3p, -1=no clip; 10/11 = 10X CR4 5/3p clip + uint32 N; + uint32 NafterAd; + string adSeq; + vector adSeqNum; + double adMMp; + + //clipped info from clipChunk + char clippedInfo; + + //clip results + uint32 clippedAdN; //adapter bases clipped + uint32 clippedAdMM; //adapter mismatches + uint32 clippedN; //total number of bases clipped + + ClipCR4 *cr4; //CR4 clipping structure + + void initialize(uint32 Nin, const string &adSeqIn, uint32 afterAdNin, double adMMpIn); + uint32 clip(uint &Lread, char *SeqNum); + void clipChunk(char *chArr, uint64 chSize); + +}; + +#endif \ No newline at end of file diff --git a/source/ClipMate_clip.cpp b/source/ClipMate_clip.cpp new file mode 100644 index 00000000..406f23ea --- /dev/null +++ b/source/ClipMate_clip.cpp @@ -0,0 +1,78 @@ +#include "ParametersClip.h" +#include "Parameters.h" +#include "SequenceFuns.h" + +uint32 ClipMate::clip(uint &Lread, char *seqNum) +{ + clippedN=0; + + if (type<0) + return 0; //no clip for this mate + + uint LreadOld=Lread; + + if (N>0) {//clip N bases + if (Lread>N) { + Lread -= N; // for 3p this is all + clippedN += N; + if (type==0) {//5p + memmove(seqNum, seqNum+N, Lread); + }; + } else { + Lread=0; + clippedN=LreadOld; + } + }; + + if (adSeq.length()>0) {//clip adapter + switch (type) { + /* not implemented yet + case 0: {//5p - not tested yet + vector vecMM({20, 22, 24, 30, 40, 50, 60, 70, 80, 90}); + clippedAdN = localSearchGeneral(seqNum, Lread, adSeqNum, -(int32)adSeqNum.size()+1, (int32)Lread-(int32)adSeqNum.size(), adMMp, vecMM, clippedAdMM); + memmove(seqNum, seqNum+clippedAdN, Lread-clippedAdN); + break; + }; + */ + case 1: {//3p + clippedAdN = Lread-localSearch(seqNum, Lread, adSeqNum.data(), adSeqNum.size(), adMMp); + break; + /* new way, not tested properly + uint64 clippedAdN1 = Lread-localSearch(seqNum, Lread, adSeqNum.data(), adSeqNum.size(), adMMp); + + //clippedAdN = localSearchGeneral(seqNum, Lread, adSeqNum, 0, Lread, adMMp, clippedAdMM); + vector vecMM({20, 23, 26, 30, 40, 50, 60, 70, 80, 90}); + clippedAdN = localSearchGeneral(seqNum, Lread, adSeqNum, Lread-1, -1, adMMp, vecMM, clippedAdMM); + + Lread=Lread; + */ + }; + case 10: {//5p: CR4 + clippedAdN = min( (uint32)clippedInfo, (uint32)Lread ); + memmove(seqNum, seqNum+clippedAdN, Lread-clippedAdN); + break; + }; + case 11: {//3p: CR4, polyA + clippedAdN = cr4->polyTail3p(seqNum, Lread); + }; + }; + + Lread -= clippedAdN; + clippedN += clippedAdN; + }; + + if (NafterAd>0) { + if (Lread > NafterAd) { + Lread -= NafterAd; + clippedN += NafterAd; + if (type==0) {//5p. For 3p, no need to move sequence + memmove(seqNum, seqNum+NafterAd, Lread); + }; + } else {//0-length after clipping + Lread=0; + clippedN=LreadOld; + }; + }; + + return clippedN; +}; diff --git a/source/ClipMate_clipChunk.cpp b/source/ClipMate_clipChunk.cpp new file mode 100644 index 00000000..edfadffe --- /dev/null +++ b/source/ClipMate_clipChunk.cpp @@ -0,0 +1,62 @@ +#include "ParametersClip.h" +#include "Parameters.h" +#include "SequenceFuns.h" + +inline char* findChar(char *arr, char c); + +void ClipMate::clipChunk(char *chArr, uint64 chSize) +{//clipping adapters from a chunk of reads + if (type != 10) //type=10 for CellRanger4 5' clipping. + return; + + char *chA1 = chArr; + bool chGood = true; //=true after teh end of the chunk + while (chGood) {//cycle over all + + int dbN1 = cr4->dbN; //maybe changed to a smaller value in the loop + int idb = 0; + for ( ; idbdbN; idb++) { + chA1 = findChar(chA1, '\n')+1; //skip read name + + char *chA2 = findChar(chA1, '\n'); + uint32 rL = (uint32) (chA2-chA1); + //debug + string tmp1(chA1, 91); + + + + cr4->opalFillOneSeq(idb, chA1, rL); + + cr4->storeClip[idb] = (uint8*) (chA2+1);//store the position of "+" character - we will record the clipped length there + + //before the next one + chA1 = chA2 + 3 + rL + 1; //start of the next read: skip \n+\n, quality=read lengt, \n + if (chA1 > chArr+chSize) { + chGood = false; + dbN1 = idb+1; + break; + }; + }; + + cr4->opalAlign((uint8_t*) adSeqNum.data(), adSeqNum.size(), dbN1); + + for (int idb=0; idbopalRes[idb].endLocationTarget+1; + int S = cr4->opalRes[idb].score; + + bool L0 = S<20 || (S==20 && L>26) || (S==21 && L>30); + + *cr4->storeClip[idb] = (uint8) (L0 ? 0 : L); + }; + }; + +}; + +inline char* findChar(char *arr, char c) +{//find character in a character array. No check for out of boundary. + char* cArr=arr; + while (*cArr != c) + ++cArr; + + return cArr; +}; \ No newline at end of file diff --git a/source/ClipMate_initialize.cpp b/source/ClipMate_initialize.cpp new file mode 100644 index 00000000..cae758e0 --- /dev/null +++ b/source/ClipMate_initialize.cpp @@ -0,0 +1,32 @@ +#include "ClipMate.h" +#include "Parameters.h" +#include "SequenceFuns.h" + +void ClipMate::initialize(uint32 Nin, const string &adSeqIn, uint32 NafterAdin, double adMMpIn) +{ + N=Nin; + + adSeq=adSeqIn; + if (adSeq=="-") { + adSeq=""; + } else { + if ( adSeq=="polyA") { + adSeqNum.clear(); //it should be empty, but just in case... + adSeqNum.resize(DEF_readSeqLengthMax, 0); //fill with A=0 + } else { + adSeqNum.resize(adSeq.size(),0); + convertNucleotidesToNumbers(adSeq.data(), adSeqNum.data(), adSeqNum.size()); + }; + }; + + if (N==0 && adSeq=="") + type=-1; + + if (type==10) + cr4 = new ClipCR4; + + NafterAd=NafterAdin; + adMMp=adMMpIn; +}; + + diff --git a/source/ErrorWarning.cpp b/source/ErrorWarning.cpp index a23d1949..f51d944e 100644 --- a/source/ErrorWarning.cpp +++ b/source/ErrorWarning.cpp @@ -5,10 +5,12 @@ #include "TimeFunctions.h" #include "GlobalVariables.h" -void exitWithError(string messageOut, ostream &streamOut1, ostream &streamOut2, int errorInt, Parameters &P) { +void exitWithError(string messageOut, ostream &streamOut1, ostream &streamOut2, int errorInt, Parameters &P) +{ + if (P.runThreadN>1) + pthread_mutex_lock(&g_threadChunks.mutexError); time_t timeCurrent; time( &timeCurrent); - if (P.runThreadN>1) pthread_mutex_lock(&g_threadChunks.mutexError); if (streamOut1.good()) { streamOut1 << "\n" << messageOut << endl << timeMonthDayTime(timeCurrent) <<" ...... FATAL ERROR, exiting\n" <1) pthread_mutex_lock(&g_threadChunks.mutexError); +void warningMessage(string messageOut, ostream &streamOut1, ostream &streamOut2, Parameters &P) +{ + if (P.runThreadN>1) + pthread_mutex_lock(&g_threadChunks.mutexError); if (streamOut1.good()) { - streamOut1 << "WARNING: " << messageOut << " : " << timeMonthDayTime(timeCurrent) <1) + pthread_mutex_unlock(&g_threadChunks.mutexError); +}; diff --git a/source/GTF.cpp b/source/GTF.cpp new file mode 100755 index 00000000..f572a2c8 --- /dev/null +++ b/source/GTF.cpp @@ -0,0 +1,171 @@ +#include "GTF.h" + +#include "ErrorWarning.h" +#include "streamFuns.h" +#include "TimeFunctions.h" + +GTF::GTF(Genome &genome, Parameters &P, const string &dirOut, SjdbClass &sjdbLoci) + : genome(genome), P(P), dirOut(dirOut), sjdbLoci(sjdbLoci), superTrome(P) + {//initialize; load gtf file; returns number of added junctions + + if (genome.sjdbOverhang==0 || genome.pGe.sjdbGTFfile=="-") {//no GTF + gtfYes=false; + return; + }; + gtfYes=true; + mkdir(dirOut.c_str(), P.runDirPerm); + + time_t rawTime; + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) <<" ..... processing annotations GTF\n" <logStdOut << timeMonthDayTime(rawTime) <<" ..... processing annotations GTF\n" < transcriptIDnumber, geneIDnumber; + + ifstream sjdbStreamIn ( genome.pGe.sjdbGTFfile.c_str() ); + if (sjdbStreamIn.fail()) { + ostringstream errOut; + errOut << "FATAL error, could not open file pGe.sjdbGTFfile=" << genome.pGe.sjdbGTFfile <<"\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + }; + + if (genome.chrNameIndex.size()==0) { + for (uint64 ii=0;ii> chr1 >> ddd2 >> featureType; + if (chr1.substr(0,1)!="#" && featureType==genome.pGe.sjdbGTFfeatureExon) { + exonN++; + }; + }; + + if (exonN==0) { + ostringstream errOut; + errOut << "Fatal INPUT FILE error, no ""exon"" lines in the GTF file: " << genome.pGe.sjdbGTFfile <<"\n"; + errOut << "Solution: check the formatting of the GTF file, it must contain some lines with ""exon"" in the 3rd column.\n"; + errOut << " Make sure the GTF file is unzipped.\n"; + errOut << " If exons are marked with a different word, use --sjdbGTFfeatureExon .\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + }; + + exonLoci.resize(exonN); + + exonN=0;//will re-calculate + sjdbStreamIn.clear(); + sjdbStreamIn.seekg(0,ios::beg); + while (sjdbStreamIn.good()) { + + string oneLine,chr1,ddd2,featureType; + getline(sjdbStreamIn,oneLine); + istringstream oneLineStream (oneLine); + + oneLineStream >> chr1 >> ddd2 >> featureType; + if (chr1.substr(0,1)!="#" && featureType==genome.pGe.sjdbGTFfeatureExon) {//exonic line, process + + if (genome.pGe.sjdbGTFchrPrefix!="-") chr1=genome.pGe.sjdbGTFchrPrefix + chr1; + + if (genome.chrNameIndex.count(chr1)==0) {//chr not in Genome + P.inOut->logMain << "WARNING: while processing sjdbGTFfile=" << genome.pGe.sjdbGTFfile <<": chromosome '"<logMain << oneLine <<"\n"<> ex1 >> ex2 >> ddd2 >> str1 >> ddd2; //read all fields except the last + if ( ex2 > genome.chrLength[genome.chrNameIndex[chr1]] ) { + warningMessage("while processing sjdbGTFfile=" + genome.pGe.sjdbGTFfile + ", line:\n" + oneLine + "\n exon end = " + to_string(ex2) + \ + " is larger than the chromosome " + chr1 + " length = " + to_string(genome.chrLength[genome.chrNameIndex[chr1]] ) + " , will skip this exon\n", \ + std::cerr, P.inOut->logMain, P); + continue; + }; + + string oneLine1; + getline(oneLineStream, oneLine1);//get the last field + replace(oneLine1.begin(),oneLine1.end(),';',' ');//to separate attributes + replace(oneLine1.begin(),oneLine1.end(),'=',' ');//for GFF3 processing + replace(oneLine1.begin(),oneLine1.end(),'\t',' ');//replace tabs + replace(oneLine1.begin(),oneLine1.end(),'\"',' ');//now the only separator is space + + //string trID(""), gID(""), attr1(""),gName(""),gBiotype(""); + vector> exAttrNames({ {genome.pGe.sjdbGTFtagExonParentTranscript}, {genome.pGe.sjdbGTFtagExonParentGene}, genome.pGe.sjdbGTFtagExonParentGeneName, genome.pGe.sjdbGTFtagExonParentGeneType }); //trID, gID, gName, gBiotype + vector exAttr; //trID, gID, gName, gBiotype + exAttr.resize(exAttrNames.size()); + + for (uint32 ii=0; iilogMain << "WARNING: while processing pGe.sjdbGTFfile=" << genome.pGe.sjdbGTFfile <<": no transcript_id for line:\n"; + P.inOut->logMain << oneLine <<"\n"<logMain << "WARNING: while processing pGe.sjdbGTFfile=" << genome.pGe.sjdbGTFfile <<": no gene_id for line:\n"; + P.inOut->logMain << oneLine <<"\n"< (exAttr[0],(uint64) transcriptIDnumber.size()));//insert new element if necessary with a new numeric value + if (transcriptID.size() < transcriptIDnumber.size()) {//new transcript + transcriptID.push_back(exAttr[0]); + if (str1=='+') { + transcriptStrand.push_back(1); + } else if (str1=='-') { + transcriptStrand.push_back(2); + } else { + transcriptStrand.push_back(0); + }; + }; + + geneIDnumber.insert(std::pair (exAttr[1],(uint64) geneIDnumber.size()));//insert new element if necessary with a $ + if (geneID.size() < geneIDnumber.size()) {//new gene is added + geneID.push_back(exAttr[1]); + geneAttr.push_back({exAttr[2],exAttr[3]}); + }; + + exonLoci[exonN][exT]=transcriptIDnumber[exAttr[0]]; + exonLoci[exonN][exS]=ex1+genome.chrStart[genome.chrNameIndex[chr1]]-1; + exonLoci[exonN][exE]=ex2+genome.chrStart[genome.chrNameIndex[chr1]]-1; + exonLoci[exonN][exG]=geneIDnumber[exAttr[1]]; + ++exonN; + };//if (chr1.substr(0,1)!="#" && featureType=="exon") + };// + + if (exonN==0) { + ostringstream errOut; + errOut << "Fatal INPUT FILE error, no valid ""exon"" lines in the GTF file: " << genome.pGe.sjdbGTFfile <<"\n"; + errOut << "Solution: check the formatting of the GTF file. One likely cause is the difference in chromosome naming between GTF and FASTA file.\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + }; + + exonLoci.resize(exonN); //previous exonLoci.size() was an estimate, need to reszie to the actual value + + return; +}; diff --git a/source/GTF.h b/source/GTF.h new file mode 100755 index 00000000..3c2b22b8 --- /dev/null +++ b/source/GTF.h @@ -0,0 +1,36 @@ +#ifndef H_GTF +#define H_GTF + +#include "IncludeDefine.h" +#include "Parameters.h" +#include "SjdbClass.h" +#include "Genome.h" +#include "SuperTranscriptome.h" + +class GTF { +private: + Genome &genome; + Parameters &P; + string dirOut; + SjdbClass &sjdbLoci; +public: + bool gtfYes; + + enum {exT,exS,exE,exG,exL}; //indexes in the exonLoci array + uint64 exonN; + vector> exonLoci; + vector transcriptStrand; + vector transcriptID, geneID; + vector> geneAttr; + + vector> transcriptSeq;//sequences of normal transcripts + vector> transcriptStartEnd;//normal transcripts start/end in the normal genome + + SuperTranscriptome superTrome; + + GTF(Genome &genomeIn, Parameters &Pin, const string &dirOut, SjdbClass &sjdbLoci); + uint64 transcriptGeneSJ(const string &dirOut); + void superTranscript(); +}; + +#endif diff --git a/source/GTF_superTranscript.cpp b/source/GTF_superTranscript.cpp new file mode 100755 index 00000000..ec774c1b --- /dev/null +++ b/source/GTF_superTranscript.cpp @@ -0,0 +1,257 @@ +/* +* Created by Fahimeh Mirhaj on 5/30/19. +*/ + +#include "GTF.h" +#include "streamFuns.h" +#include "genomeParametersWrite.h" + +void GTF::superTranscript() { + if (P.pGe.gTypeString!="Transcriptome" && P.pGe.gTypeString!="SuperTranscriptome") { + return; + }; + + //write full genome + mkdir((genome.pGe.gDir+"/fullGenome").c_str(), P.runDirPerm); + genomeParametersWrite(genome.pGe.gDir+"/fullGenome/genomeParameters.txt", P, ERROR_OUT, genome); + genome.writeChrInfo(genome.pGe.gDir+"/fullGenome/"); + genome.writeGenomeSequence(genome.pGe.gDir+"/fullGenome/"); + + uint64 nMinusStrandOffset=genome.nGenome; + for(uint64 i = 0; i < exonLoci.size(); i++) {//convert (-)strand exons coordinates + uint64 transId = exonLoci[i][exT]; + if(transcriptStrand[transId] == 2) { + uint64 temp = exonLoci[i][exS]; + exonLoci[i][exS] = 2*nMinusStrandOffset - 1 - exonLoci[i][exE]; + exonLoci[i][exE] = 2*nMinusStrandOffset - 1 - temp; + }; + }; + + vector> mergedIntervals; + {//create mergedIntervals=union of all exons, and condensed genome + //exonLoci are transformed into coordinates in condensed genome + //sort by exon start position + sort(exonLoci.begin(), exonLoci.end(), + [](const array& e1, const array& e2) { + return e1[exS] < e2[exS]; + }); + + //mergedIntervals + uint64 gapValue = exonLoci[0][exS]; + array curr = {exonLoci[0][exS], exonLoci[0][exE]}; //intervals[0] + exonLoci[0][exS] = 0; + exonLoci[0][exE] -= gapValue; + + for(uint64 i = 1; i < exonLoci.size(); ++i) { + if(exonLoci[i][exS] <= curr[1]+1) { + curr[1] = max(curr[1], exonLoci[i][exE]); + } else { + gapValue += exonLoci[i][exS] - curr[1] - 1; + mergedIntervals.push_back(curr); + curr = {exonLoci[i][exS], exonLoci[i][exE]}; + }; + exonLoci[i][exS] -= gapValue; + exonLoci[i][exE] -= gapValue; + }; + mergedIntervals.push_back(curr); + + //Condensed genome (a.k.a SuperTranscriptome) sequence + for(const auto& p: mergedIntervals) { + for(uint64 j = p[0]; j <= p[1]; ++j) { + superTrome.seqConcat.push_back((uint8) genome.G[j]); + }; + }; + P.inOut->logMain << "SuperTranscriptome (condensed) genome length = " << superTrome.seqConcat.size() <> superTrStartEnd; + vector mergedIntervalsSuperTrIndex(mergedIntervals.size()); + uint64 miI=0, miLen=0; + {//superTrStartEnd=coordinates in Condendsed genome + vector> transcriptStartEndSorted = transcriptStartEnd;//sorted transript intervals + sort(transcriptStartEndSorted.begin(), transcriptStartEndSorted.end(), + [](const array& t1, const array& t2) { + return t1[0] < t2[0]; + }); + auto curr = transcriptStartEndSorted.front(); + for(const auto& p: transcriptStartEndSorted) {//if transcript intervals overlap by >=1 base, merge them into SuperTranscripts + + while (miLen(superTrome.seqConcat.begin()+p[0], superTrome.seqConcat.begin()+p[1]+1)); + maxSTlen=max(maxSTlen,p[1]-p[0]); + }; + P.inOut->logMain << "Number of superTranscripts = " << superTrStartEnd.size() <<"; max length = " <superTrStartEnd[ist][1]) + ++ist; + superTrome.trIndex[ee[exT]]=ist; + }; + + superTrome.trStartEnd.resize(transcriptID.size()); + for(uint i = 0; i < transcriptStartEnd.size(); i++) { + superTrome.trStartEnd[i][0] = transcriptStartEnd[i][0] - superTrStartEnd[superTrome.trIndex[i]][0]; + superTrome.trStartEnd[i][1] = transcriptStartEnd[i][1] - superTrStartEnd[superTrome.trIndex[i]][0]; + }; + //////////////////Normal transcripts + sort(exonLoci.begin(), exonLoci.end(), + [](const array& e1, const array& e2) { + return (e1[exT] < e2[exT]) || ((e1[exT] == e2[exT]) && (e1[exS] < e2[exS])); + }); + + transcriptSeq.resize(transcriptID.size()); + for(uint64 i = 0; i < exonLoci.size(); i++) { + transcriptSeq[exonLoci[i][exT]].insert( + transcriptSeq[exonLoci[i][exT]].end(), + superTrome.seqConcat.begin()+exonLoci[i][exS], + superTrome.seqConcat.begin()+exonLoci[i][exE] + 1 + ); + }; + + //output normal transcript sequences + vector numToCharConverter{'A','C','G','T','N'}; + ofstream & trSeqOut = ofstrOpen(P.pGe.gDir+"/transcriptSequences.fasta",ERROR_OUT, P); + for (uint64 ii = 0; ii < transcriptSeq.size(); ii++) { + trSeqOut << ">" << transcriptID[ii] << "\n"; + for(uint64 jj = 0; jj < transcriptSeq[ii].size(); jj++) { + trSeqOut << numToCharConverter[transcriptSeq[ii][jj]]; + }; + trSeqOut << "\n"; + }; + trSeqOut.close(); + ofstream & sutrSeqOut = ofstrOpen(P.pGe.gDir+"/superTranscriptSequences.fasta",ERROR_OUT, P); + for (uint64 ii = 0; ii < superTrome.seq.size(); ii++) { + sutrSeqOut << ">st" << to_string(ii) << "\n"; + for(uint64 jj = 0; jj < superTrome.seq[ii].size(); jj++) { + sutrSeqOut << numToCharConverter[superTrome.seq[ii][jj]]; + }; + sutrSeqOut << "\n"; + }; + sutrSeqOut.close(); + + + // splice junctions, in superTranscript coordinates. Here, sjS is the last base of donor exon, and sjE is the last base of acceptor exon + for(uint64 i = 1; i < exonLoci.size(); i++) {//exonLoci are still sorted by transcript index and start coordinate + if (exonLoci[i][exT]==exonLoci[i-1][exT]) {//same transcript + if (exonLoci[i][exS] > (exonLoci[i-1][exE]+1)) {//gap >0, otherwise we do not need to record the junction (may need it in the future for other purposes though) + uint64 sti=superTrome.trIndex[exonLoci[i][exT]];//ST index + uint64 sts=superTrStartEnd[sti][0]; //superTranscript start + superTrome.sj.emplace_back();//add one element + superTrome.sj.back().start = (uint32)(exonLoci[i-1][exE]-sts);//start at the last base of the exon + superTrome.sj.back().end = (uint32)(exonLoci[i] [exS]-sts);//end at the first base of the next exon + superTrome.sj.back().tr = exonLoci[i][exT];//the transcript info is retained, thus there will be duplicate junctions that belong to different transcripts + superTrome.sj.back().super = sti; + }; + }; + }; + superTrome.sjCollapse(); + + //save some variables for real genome here? + + //replace the Genome sequence and all necessary parameters for downstream genome generation + if (P.pGe.gTypeString=="Transcriptome") { + genome.concatenateChromosomes(transcriptSeq, transcriptID, genome.genomeChrBinNbases); + gtfYes=false; //annotations were converted into transcript sequences and are no longer used + P.sjdbInsert.yes=false; //actually, it might pe possible to add splice junctions on top of the transcriptome + } else if (P.pGe.gTypeString=="SuperTranscriptome") { + vector superTranscriptID(superTrStartEnd.size()); + for (uint64 ii=0; ii& e1, const array& e2) + { + return e1[exS] < e2[exS]; + } + ); + //shift exonLoci according to chrStart + uint64 ist=0; + for (auto &ee: exonLoci) { + if (ee[exS]>superTrStartEnd[ist][1]) + ++ist; + ee[exS]+=genome.chrStart[ist]-superTrStartEnd[ist][0]; + ee[exE]+=genome.chrStart[ist]-superTrStartEnd[ist][0]; + }; + }; + + //output conversion blocks + ofstream & convStream = ofstrOpen(P.pGe.gDir+"/fullGenome/conversionToFullGenome.tsv",ERROR_OUT, P); + convStream << mergedIntervals.size() <<'\t'<< nMinusStrandOffset <<'\n'; + + uint64 condGstart=0; //start of the interval in the condensed genome + for (uint64 ib=0; ibsuperTrStartEnd[iSuTr][1]) +// ++iSuTr; + }; + convStream.close(); +} + +void Genome::concatenateChromosomes(const vector> &vecSeq, const vector &vecName, const uint64 padBin) +{//concatenate chromosome sequence into linear genome, with padding + //changes genome: chrStart, chrLen, chrName, G + nChrReal=vecSeq.size(); + chrLength.resize(nChrReal,0); + chrStart.resize(nChrReal+1,0); + chrName=vecName; + chrNameIndex.clear(); + for (uint32 ii=0; ii +#include + +#define GTF_extrLoci_size 6 +#define GTF_extrTrStart(ii) ((ii)*GTF_extrLoci_size) +#define GTF_extrTrEnd(ii) ((ii)*GTF_extrLoci_size+1) +#define GTF_extrTrID(ii) ((ii)*GTF_extrLoci_size+2) +#define GTF_extrExStart(ii) ((ii)*GTF_extrLoci_size+3) +#define GTF_extrExEnd(ii) ((ii)*GTF_extrLoci_size+4) +#define GTF_extrGeID(ii) ((ii)*GTF_extrLoci_size+5) + +#define GTF_exgeLoci_size 5 +#define GTF_exgeExStart(ii) ((ii)*GTF_exgeLoci_size+0) +#define GTF_exgeExEnd(ii) ((ii)*GTF_exgeLoci_size+1) +#define GTF_exgeExStrand(ii) ((ii)*GTF_exgeLoci_size+2) +#define GTF_exgeGeID(ii) ((ii)*GTF_exgeLoci_size+3) +#define GTF_exgeTrID(ii) ((ii)*GTF_exgeLoci_size+4) + +uint64 GTF::transcriptGeneSJ(const string &dirOut) +{//sort exonLoci by transcript ID and exon coordinates + //fills sjdbLoci from GTF junctions + + if (!gtfYes) + return 0; + + exonN=exonLoci.size(); + qsort((void*) exonLoci.data(), exonN, sizeof(uint64)*exL, funCompareUint2); + + {//exon-gene data structures: exon start/end/strand/gene/transcript + //re-sort exons by exons loci + uint64* exgeLoci=new uint64 [exonN*GTF_exgeLoci_size]; //this also contains transcripts start and end + + for (uint64 iex=0; iex); + + ofstream & exgeOut = ofstrOpen(dirOut+"/exonGeTrInfo.tab",ERROR_OUT,P); + exgeOut<); + + ofstream trOut ((dirOut+"/transcriptInfo.tab").c_str()); + trOut<> genome.pGe.gChrBinNbits]; + if ( exonLoci[iex][exS]<=exonLoci[iex-1][exE]+1 ) {//touching - nothing to do + } else if ( exonLoci[iex][exS]<=exonLoci[iex-1][exE] ) {//overlapping + P.inOut->logMain << "WARNING: while processing pGe.sjdbGTFfile=" << genome.pGe.sjdbGTFfile <<": overlapping exons:\n"; + P.inOut->logMain << genome.chrName[chr1] <<"\t"<< exonLoci[iex-1][exS]+1-genome.chrStart[chr1] << "\t"<< exonLoci[iex-1][exE]+1-genome.chrStart[chr1] <<"\n"; + P.inOut->logMain << genome.chrName[chr1] <<"\t"<< exonLoci[iex][exS] +1-genome.chrStart[chr1] << "\t"<< exonLoci[iex][exE] +1-genome.chrStart[chr1] <<"\n"; + } else { + sjLoci[sjN*sjStride]=exonLoci[iex-1][exE]+1; + sjLoci[sjN*sjStride+1]=exonLoci[iex][exS]-1; + sjLoci[sjN*sjStride+2]=(uint64) transcriptStrand[trIDn]; + sjLoci[sjN*sjStride+3]=exonLoci[iex][exG]+1;//genes are numbered from 1 + sjN++; + }; + } else { + trIDn=exonLoci[iex][exT]; + }; + }; + + qsort((void*) sjLoci, sjN, sizeof(uint64)*sjStride, funCompareUint2); + + char strandChar[3]={'.','+','-'}; + uint64 sjdbN1=sjdbLoci.chr.size(); + sjdbLoci.gene.resize(sjdbN1); //need to resize in case sjdbLoci was loaded from files without gene attribute. TODO make sure gene is always present + for (uint64 ii=0;ii> genome.pGe.gChrBinNbits]; + sjdbLoci.chr.push_back(genome.chrName[chr1]); + sjdbLoci.start.push_back(sjLoci[ii*sjStride]+1-genome.chrStart[chr1]); + sjdbLoci.end.push_back(sjLoci[ii*sjStride+1]+1-genome.chrStart[chr1]); + sjdbLoci.str.push_back(strandChar[sjLoci[ii*sjStride+2]]); + sjdbLoci.gene.push_back({sjLoci[ii*sjStride+3]}); + } else { + sjdbLoci.gene.back().insert(sjLoci[ii*sjStride+3]); + }; + }; + + ofstream sjdbList ((dirOut+"/sjdbList.fromGTF.out.tab").c_str()); + for (uint64 ii=sjdbN1;iilogMain << "Processing pGe.sjdbGTFfile=" << genome.pGe.sjdbGTFfile <<", found:\n"; + P.inOut->logMain << "\t\t" << transcriptID.size() <<" transcripts\n" << "\t\t" << exonN << " exons (non-collapsed)\n" << "\t\t" << sjdbLoci.chr.size()-sjdbN1 << " collapsed junctions\n"; + P.inOut->logMain << "Total junctions: " <logMain << timeMonthDayTime(rawTime) <<" ..... finished GTF processing\n\n" < #include -//addresses with respect to shmStart of several genome values -#define SHM_sizeG 0 -#define SHM_sizeSA 8 -#define SHM_startG 16 -// #define SHM_startSA 24 -// -// //first available byt of the shm -// #define SHM_startSHM 32 - - //arbitrary number for ftok function #define SHM_projectID 23 -Genome::Genome (Parameters &Pin ): pGe(Pin.pGe), sharedMemory(NULL), P(Pin), shmStart(NULL) { +Genome::Genome (Parameters &P, ParametersGenome &pGe): shmStart(NULL), P(P), pGe(pGe), sharedMemory(NULL) +{ shmKey=ftok(pGe.gDir.c_str(),SHM_projectID); - + genomeOut.g=this;//will change if genomeOut is different from genomeMain + genomeOut.convYes=false; sjdbOverhang = pGe.sjdbOverhang; //will be re-defined later if another value was used for the generated genome sjdbLength = pGe.sjdbOverhang==0 ? 0 : pGe.sjdbOverhang*2+1; }; @@ -84,470 +75,6 @@ uint Genome::OpenStream(string name, ifstream & stream, uint size) }; -void Genome::genomeLoad(){//allocate and load Genome - - time_t rawtime; - time ( &rawtime ); - *(P.inOut->logStdOut) << timeMonthDayTime(rawtime) << " ..... loading genome\n" <logMain << "Reading genome generation parameters:\n"; - - //read genome internal parameters - while (parFile.good()) { - string word1; - parFile >> word1; - if (word1=="###") { - parFile >> word1; - if (word1=="GstrandBit") { - uint gsb1=0; - parFile >> gsb1; - GstrandBit=(uint8) gsb1; - P.inOut->logMain << "### GstrandBit=" << (uint) GstrandBit <<"\n"; - } else { - P.inOut->logMain << "### " <logMain <logMain, EXIT_CODE_GENOME_FILES, P); - }; - - //check genome version - if (P1.versionGenome.size()==0) {// - ostringstream errOut; - errOut << "EXITING because of FATAL ERROR: read no value for the versionGenome parameter from genomeParameters.txt file\n"; - errOut << "SOLUTION: please re-generate genome from scratch with the latest version of STAR\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); - } else if (P1.versionGenome == P.versionGenome) {// - P.inOut->logMain << "Genome version is compatible with current STAR\n"; - } else { - ostringstream errOut; - errOut << "EXITING because of FATAL ERROR: Genome version: " << P1.versionGenome << " is INCOMPATIBLE with running STAR version: "<< STAR_VERSION <<"\n"; - errOut << "SOLUTION: please re-generate genome from scratch with running version of STAR, or with version: " << P.versionGenome <<"\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); - }; - - //find chr starts from files - chrInfoLoad(); - - //check if sjdbInfo.txt exists => genome was generated with junctions - bool sjdbInfoExists=false; - struct stat sjdb1; - if ( stat( (pGe.gDir+"/sjdbInfo.txt").c_str(), &sjdb1) == 0 ) - {//file exists - sjdbInfoExists=true; - }; - - if ( P.sjdbInsert.yes && sjdbInfoExists && P1.pGe.sjdbInsertSave=="") - {//if sjdbInsert, and genome had junctions, and genome is old - it should be re-generated with new STAR - ostringstream errOut; - errOut << "EXITING because of FATAL ERROR: old Genome is INCOMPATIBLE with on the fly junction insertion\n"; - errOut << "SOLUTION: please re-generate genome from scratch with the latest version of STAR\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); - }; - - //record required genome parameters in P - pGe.gSAindexNbases=P1.pGe.gSAindexNbases; - pGe.gChrBinNbits=P1.pGe.gChrBinNbits; - genomeChrBinNbases=1LLU<0) - {//genomeFileSize was recorded in the genomeParameters file, copy the values to P - pGe.gFileSizes = P1.pGe.gFileSizes; - }; - - if (P.parArray.at(pGe.sjdbOverhang_par)->inputLevel==0 && P1.pGe.sjdbOverhang>0) - {//if --sjdbOverhang was not defined by user and it was defined >0 at the genome generation step, then use pGe.sjdbOverhang from the genome generation step - pGe.sjdbOverhang=P1.pGe.sjdbOverhang; - P.inOut->logMain << "--sjdbOverhang = " << pGe.sjdbOverhang << " taken from the generated genome\n"; - } else if (sjdbInfoExists && P.parArray.at(pGe.sjdbOverhang_par)->inputLevel>0 && pGe.sjdbOverhang!=P1.pGe.sjdbOverhang) - {//if pGe.sjdbOverhang was defined at the genome generation step,the mapping step value has to agree with it - ostringstream errOut; - errOut << "EXITING because of fatal PARAMETERS error: present --sjdbOverhang="<logMain, EXIT_CODE_GENOME_FILES, P); - }; - - sjdbOverhang = pGe.sjdbOverhang; - sjdbLength = pGe.sjdbOverhang==0 ? 0 : pGe.sjdbOverhang*2+1; - - P.inOut->logMain << "Started loading the genome: " << asctime (localtime ( &rawtime ))<<"\n"<logMain << "Read from SAindex: pGe.gSAindexNbases=" << pGe.gSAindexNbases <<" nSAi="<< nSAi <logMain << "nGenome=" << nGenome << "; nSAbyte=" << nSAbyte <logMain <<"GstrandBit="<SetErrorStream(P.inOut->logStdOut); - - if (!sharedMemory->NeedsAllocation()) - P.inOut->logMain <<"Found genome in shared memory\n"<NeedsAllocation()) {//did not find genome in shared memory, nothing to kill - ostringstream errOut; - errOut << "EXITING: Did not find the genome in memory, did not remove any genomes from shared memory\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); - } else { - sharedMemory->Clean(); - P.inOut->logMain <<"DONE: removed the genome from shared memory\n"<NeedsAllocation()){ - P.inOut->logMain <<"Allocating shared memory for genome\n"<Allocate(shmSize); - }; - } catch (const SharedMemoryException & exc){ - HandleSharedMemoryException(exc, shmSize); - }; - - shmStart = (char*) sharedMemory->GetMapped(); - shmNG= (uint*) (shmStart+SHM_sizeG); - shmNSA= (uint*) (shmStart+SHM_sizeSA); - - if (!sharedMemory->IsAllocator()) { - // genome is in shared memory or being loaded - // wait for the process that will populate it - // and record the sizes - uint iwait=0; - while (*shmNG != nGenome) { - iwait++; - P.inOut->logMain <<"Another job is still loading the genome, sleeping for 1 min\n" <logMain, EXIT_CODE_GENOME_LOADING_WAITED_TOO_LONG, P); - }; - }; - if (nSAbyte!=*shmNSA){ - ostringstream errOut; - errOut << "EXITING because of FATAL ERROR: the SA file size did not match what we found in shared memory" << "\n" << flush; - errOut << "SOLUTION: remove the shared memory chunk by running STAR with --genomeLoad Remove, and restart STAR" << flush; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INCONSISTENT_DATA, P); - }; - P.inOut->logMain << "Using shared memory for genome. key=0x" <logMain <<"Shared memory is not used for genomes. Allocated a private copy of the genome.\n"<logMain, EXIT_CODE_MEMORY_ALLOCATION, P); - }; - - } - - -// if (twopass1readsN==0) {//not 2-pass -// shmStartG=SHM_startSHM; -// shmStartSA=0; -// } else {//2-pass -// ostringstream errOut; -// errOut << "EXITING because of FATAL ERROR: 2-pass procedure cannot be used with genome already loaded im memory' "\n" ; -// errOut << "SOLUTION: check shared memory settings as explained in STAR manual, OR run STAR with --genomeLoad NoSharedMemory to avoid using shared memory\n" <logMain, EXIT_CODE_SHM, P); -// }; - - - G=G1+L; - - bool isAllocatorProcess = sharedMemory != NULL && sharedMemory->IsAllocator(); - - if (pGe.gLoad=="NoSharedMemory" || isAllocatorProcess) {//load genome and SAs from files - //load genome - P.inOut->logMain <<"Genome file size: "<logMain <<"Loading Genome ... " << flush; - uint genomeReadBytesN=fstreamReadBig(GenomeIn,G,nGenome); - P.inOut->logMain <<"done! state: good=" <logMain <<"SA file size: "<logMain <<"Loading SA ... " << flush; - genomeReadBytesN=fstreamReadBig(SAin,SA.charArray, SA.lengthByte); - P.inOut->logMain <<"done! state: good=" <logMain <<"Loading SAindex ... " << flush; - SAiInBytes +=fstreamReadBig(SAiIn,SAi.charArray, SAi.lengthByte); - P.inOut->logMain <<"done: "<logMain << "Finished loading the genome: " << asctime (localtime ( &rawtime )) <<"\n"<logMain << "Sum of all Genome bytes: " <logMain << "Sum of all SA bytes: " <logMain << "Sum of all SAi bytes: " <logMain << "pGe.gLoad=LoadAndExit: completed, the genome is loaded and kept in RAM, EXITING now.\n"<logMain, EXIT_CODE_INPUT_FILES, P); - }; - - - sjdbInfo >> sjdbN >> pGe.sjdbOverhang; - P.inOut->logMain << "Processing splice junctions database sjdbN=" <> sjdbStart[ii] >> sjdbEnd[ii] >> d1 >> d2 >> d3 >> d4; - sjdbMotif[ii] = (uint8) d1; - sjdbShiftLeft[ii] = (uint8) d2; - sjdbShiftRight[ii] = (uint8) d3; - sjdbStrand[ii] = (uint8) d4; - }; - sjDstart[ii] = sjdbStart[ii] - pGe.sjdbOverhang; - sjAstart[ii] = sjdbEnd[ii] + 1; - if (sjdbMotif[ii]==0) {//shinon-canonical junctions back to their true coordinates - sjDstart[ii] += sjdbShiftLeft[ii]; - sjAstart[ii] += sjdbShiftLeft[ii]; - }; - }; - }; - - //check and redefine some parameters - //max intron size - if (P.alignIntronMax==0 && P.alignMatesGapMax==0) { - P.inOut->logMain << "alignIntronMax=alignMatesGapMax=0, the max intron size will be approximately determined by (2^winBinNbits)*winAnchorDistNbins=" \ - << (1LLU<0 but alignMatesGapMax==0, winBinNbits will be defined by alignIntronMax - P.inOut->logMain << "To accommodate alignIntronMax="< " << "pGe.gChrBinNbits=" << pGe.gChrBinNbits << " redefining:\n"; - P.winBinNbits=pGe.gChrBinNbits; - P.inOut->logMain << "winBinNbits=" <logMain << "To accommodate alignIntronMax="<logMain, EXIT_CODE_INPUT_FILES, P); + }; + + G1out=new char[nG1allocOut]; + Gout=G1out+100; + + memset(G1out,GENOME_spacingChar,nG1allocOut);//initialize to K-1 all bytes +}; diff --git a/source/Genome.h b/source/Genome.h old mode 100644 new mode 100755 index 099a4e6d..ad409b49 --- a/source/Genome.h +++ b/source/Genome.h @@ -1,71 +1,107 @@ -#ifndef GENOME_DEF -#define GENOME_DEF +#ifndef H_Genome +#define H_Genome #include "IncludeDefine.h" #include "Parameters.h" #include "PackedArray.h" #include "SharedMemory.h" #include "Variation.h" +#include "SuperTranscriptome.h" -class Genome { - public: - char *G, *sigG; - PackedArray SA,SAinsert,SApass1,SApass2; - PackedArray SAi; - Variation *Var; - - uint nGenomeInsert, nGenomePass1, nGenomePass2, nSAinsert, nSApass1, nSApass2; - - ParametersGenome &pGe; - - //chr parameters - vector chrStart, chrLength, chrLengthAll; - uint genomeChrBinNbases, chrBinN, *chrBin; - vector chrName, chrNameAll; - map chrNameIndex; - - uint *genomeSAindexStart;//starts of the L-mer indices in the SAindex, 1<=L<=pGe.gSAindexNbases - - uint nGenome, nSA, nSAbyte, nChrReal;//genome length, SA length, # of chromosomes, vector of chromosome start loci - uint nGenome2, nSA2, nSAbyte2, nChrReal2; //same for the 2nd pass - uint nSAi; //size of the SAindex - unsigned char GstrandBit, SAiMarkNbit, SAiMarkAbsentBit; //SA index bit for strand information - uint GstrandMask, SAiMarkAbsentMask, SAiMarkAbsentMaskC, SAiMarkNmask, SAiMarkNmaskC;//maske to remove strand bit from SA index, to remove mark from SAi index - - //SJ database parameters - uint sjdbOverhang, sjdbLength; //length of the donor/acceptor, length of the sj "chromosome" =2*pGe.sjdbOverhang+1 including spacer - uint sjChrStart,sjdbN; //first sj-db chr - uint sjGstart; //start of the sj-db genome sequence - uint *sjDstart,*sjAstart,*sjStr, *sjdbStart, *sjdbEnd; //sjdb loci - uint8 *sjdbMotif; //motifs of annotated junctions - uint8 *sjdbShiftLeft, *sjdbShiftRight; //shifts of junctions - uint8 *sjdbStrand; //junctions strand, not used yet - - //sequence insert parameters - uint genomeInsertL; //total length of the sequence to be inserted on the fly - uint genomeInsertChrIndFirst; //index of the first inserted chromosome - - SharedMemory * sharedMemory; - - Genome (Parameters &Pin ); - //~Genome(); - - void freeMemory(); - void genomeLoad(); - void chrBinFill(); - void chrInfoLoad(); - - void insertSequences(); - - void genomeGenerate(); - - private: - Parameters &P; - key_t shmKey; - char *shmStart; - char *G1; //pointer -200 of G - uint OpenStream(string name, ifstream & stream, uint size); - void HandleSharedMemoryException(const SharedMemoryException & exc, uint64 shmSize); +class GTF; +class Genome { +private: + key_t shmKey; + char *shmStart; + uint OpenStream(string name, ifstream & stream, uint size); + void HandleSharedMemoryException(const SharedMemoryException & exc, uint64 shmSize); +public: + Parameters &P; + ParametersGenome &pGe; + SharedMemory *sharedMemory; + + enum {exT,exS,exE,exG,exL}; //indexes in the exonLoci array from GTF + + char *G, *G1; + uint64 nGenome, nG1alloc; + PackedArray SA,SAinsert,SApass1,SApass2; + PackedArray SAi; + Variation *Var; + + uint nGenomeInsert, nGenomePass1, nGenomePass2, nSAinsert, nSApass1, nSApass2; + + + //chr parameters + vector chrStart, chrLength, chrLengthAll; + uint genomeChrBinNbases, chrBinN, *chrBin; + vector chrName, chrNameAll; + map chrNameIndex; + + uint *genomeSAindexStart;//starts of the L-mer indices in the SAindex, 1<=L<=pGe.gSAindexNbases + + uint nSA, nSAbyte, nChrReal;//genome length, SA length, # of chromosomes, vector of chromosome start loci + uint nGenome2, nSA2, nSAbyte2, nChrReal2; //same for the 2nd pass + uint nSAi; //size of the SAindex + unsigned char GstrandBit, SAiMarkNbit, SAiMarkAbsentBit; //SA index bit for strand information + uint GstrandMask, SAiMarkAbsentMask, SAiMarkAbsentMaskC, SAiMarkNmask, SAiMarkNmaskC;//maske to remove strand bit from SA index, to remove mark from SAi index + + //SJ database parameters + uint sjdbOverhang, sjdbLength; //length of the donor/acceptor, length of the sj "chromosome" =2*pGe.sjdbOverhang+1 including spacer + uint sjChrStart,sjdbN; //first sj-db chr + uint sjGstart; //start of the sj-db genome sequence + uint *sjDstart,*sjAstart,*sjStr, *sjdbStart, *sjdbEnd; //sjdb loci + uint8 *sjdbMotif; //motifs of annotated junctions + uint8 *sjdbShiftLeft, *sjdbShiftRight; //shifts of junctions + uint8 *sjdbStrand; //junctions strand, not used yet + + //sequence insert parameters + uint genomeInsertL; //total length of the sequence to be inserted on the fly + uint genomeInsertChrIndFirst; //index of the first inserted chromosome + + //SuperTranscriptome genome + SuperTranscriptome *superTr; + + Genome (Parameters &P, ParametersGenome &pGe); + //~Genome(); + + void freeMemory(); + void genomeLoad(); + void genomeOutLoad(); + void chrBinFill(); + void chrInfoLoad(); + void genomeSequenceAllocate(uint64 nGenomeIn, uint64 &nG1allocOut, char*& Gout, char*& G1out); + void loadSJDB(string &genDir); + + void insertSequences(); + + //void consensusSequence(); DEPRECATED + + void genomeGenerate(); + void writeChrInfo(const string dirOut); + void concatenateChromosomes(const vector> &vecSeq, const vector &vecName, const uint64 padBin); + void writeGenomeSequence(const string dirOut); + + //transform genome coordinates + struct { + bool convYes; + bool gapsAreJunctions; + Genome *g; + string convFile; + vector> convBlocks; + uint64 nMinusStrandOffset;//offset for the (-) strand, typically=nGenomeReal + } genomeOut; + + typedef struct { + uint64 pos; + int32 len;//0: SNV, <0: deletion; >0: insertion + array seq;//sequence for SNV and insertions, empty for deletions + } VariantInfo; + + void transformGenome(GTF *gtf) ; + void transformChrLenStart(map> &vcfVariants, vector &chrStart1, vector &chrLength1); + void transformGandBlocks(map> &vcfVariants, vector &chrStart1, vector &chrLength1, vector> &transformBlocks, char *Gnew); + void transformBlocksWrite(vector> &transformBlocks); + void transformExonLoci(vector> &exonLoci, vector> &transformBlocks); }; #endif diff --git a/source/Genome_genomeGenerate.cpp b/source/Genome_genomeGenerate.cpp old mode 100644 new mode 100755 index ee5113d0..213edf7f --- a/source/Genome_genomeGenerate.cpp +++ b/source/Genome_genomeGenerate.cpp @@ -1,12 +1,14 @@ #include +#include "Genome.h" + #include "IncludeDefine.h" #include "Parameters.h" #include "SuffixArrayFuns.h" #include "PackedArray.h" #include "TimeFunctions.h" #include "ErrorWarning.h" -#include "loadGTF.h" +#include "GTF.h" #include "SjdbClass.h" #include "sjdbLoadFromFiles.h" #include "sjdbPrepare.h" @@ -86,28 +88,6 @@ inline int funCompareSuffixes ( const void *a, const void *b){ }; }; -// inline bool funCompareSuffixesBool ( const void *a, const void *b) -// { -// uint jj=0LLU; -// -// uint *ga=(uint*)((globalG-7LLU)+(*((uint*)a))); -// uint *gb=(uint*)((globalG-7LLU)+(*((uint*)b))); -// uint va=0,vb=0; -// -// while (va==vb && jj>GstrandBit) == 0; SAstr &= GstrandMask; @@ -118,18 +98,27 @@ inline uint funG2strLocus (uint SAstr, uint const N, char const GstrandBit, uint void Genome::genomeGenerate() { //check parameters - if (sjdbOverhang<=0 && (pGe.sjdbFileChrStartEnd.at(0)!="-" || pGe.sjdbGTFfile!="-")) - { + createDirectory(pGe.gDir, P.runDirPerm, "--genomeDir", P); + + {//move Log.out file into genome directory + string logfn=pGe.gDir+"Log.out"; + if ( rename( P.outLogFileName.c_str(), logfn.c_str() ) ) { + warningMessage("Could not move Log.out file from " + P.outLogFileName + " into " + logfn + ". Will keep " + P.outLogFileName +"\n", \ + std::cerr, P.inOut->logMain, P); + } else { + P.outLogFileName=logfn; + }; + }; + if (sjdbOverhang<=0 && (pGe.sjdbFileChrStartEnd.at(0)!="-" || pGe.sjdbGTFfile!="-")) { ostringstream errOut; errOut << "EXITING because of FATAL INPUT PARAMETER ERROR: for generating genome with annotations (--sjdbFileChrStartEnd or --sjdbGTFfile options)\n"; errOut << "you need to specify >0 --sjdbOverhang\n"; errOut << "SOLUTION: re-run genome generation specifying non-zero --sjdbOverhang, which ideally should be equal to OneMateLength-1, or could be chosen generically as ~100\n"; exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); - } - if (pGe.sjdbFileChrStartEnd.at(0)=="-" && pGe.sjdbGTFfile=="-") - { - if (P.parArray.at(P.pGe.sjdbOverhang_par)->inputLevel>0 && sjdbOverhang>0) - { + }; + + if (pGe.sjdbFileChrStartEnd.at(0)=="-" && pGe.sjdbGTFfile=="-") { + if (P.parArray.at(P.pGe.sjdbOverhang_par)->inputLevel>0 && sjdbOverhang>0) { ostringstream errOut; errOut << "EXITING because of FATAL INPUT PARAMETER ERROR: when generating genome without annotations (--sjdbFileChrStartEnd or --sjdbGTFfile options)\n"; errOut << "do not specify >0 --sjdbOverhang\n"; @@ -138,7 +127,7 @@ void Genome::genomeGenerate() { }; sjdbOverhang=0; }; - + //time time_t rawTime; string timeString; @@ -150,112 +139,64 @@ void Genome::genomeGenerate() { //define some parameters from input parameters genomeChrBinNbases=1LLU << pGe.gChrBinNbits; - uint nGenomeReal=genomeScanFastaFiles(P,NULL,false,*this);//first scan the fasta file to find all the sizes - chrBinFill(); - - uint L=10000;//maximum length of genome suffix - uint nG1alloc=(nGenomeReal + L)*2; - char *G1=new char[nG1alloc]; - G=G1+L; - - memset(G1,GENOME_spacingChar,nG1alloc);//initialize to K-1 all bytes - + nGenome = genomeScanFastaFiles(P,NULL,false,*this);//first scan the fasta file to find all the sizes + genomeSequenceAllocate(nGenome, nG1alloc, G, G1); genomeScanFastaFiles(P,G,true,*this); //load the genome sequence - if (pGe.gConsensusFile!="-") {//load consensus SNPs - ifstream &consIn=ifstrOpen(pGe.gConsensusFile, ERROR_OUT, "SOLUTION: check path and permission for the --genomeConsensusFile file" + pGe.gConsensusFile, P); + uint64 nGenomeTrue=0; + for (auto &cl : chrLength) + nGenomeTrue += cl; //nGenomeTrue = sum of chr lengths - map chrStartMap; - for (uint ii=0;ii (chrName[ii], chrStart[ii])); - }; + P.inOut->logMain <<"Genome sequence total length = " << nGenomeTrue << "\n"; + P.inOut->logMain <<"Genome size with padding = "<< nGenome <<"\n"; - uint nInserted=0, nWrongChr=0, nWrongRef=0, nRefN=0; - while (consIn.good()) { - string chr1, refIn, altIn, dummy; - uint start1; - char ref1,alt1; - - consIn >> chr1 >> start1 >> dummy >> refIn >> altIn; - consIn.ignore(numeric_limits::max(),'\n'); - - convertNucleotidesToNumbers(refIn.c_str(),&ref1,1); - convertNucleotidesToNumbers(altIn.c_str(),&alt1,1); - --start1;//VCF positions are 1-based - - if (chrStartMap.count(chr1)==1) {//otherwise just skip - start1+=chrStartMap[chr1]; - if (G[start1]>3) - ++nRefN; - - if (G[start1]==ref1 || G[start1]>3) { - G[start1]=alt1; - ++nInserted; - } else { - ++nWrongRef; - P.inOut->logMain << "WARNING: reference allele in consensus file does not agree with reference genome base: "; - P.inOut->logMain << chr1 <<" "<< start1-chrStartMap[chr1] <<" "<< (int) G[start1]<<" "<< (int) ref1<<" "<< (int) alt1<<"\n"; - }; - } else { - ++nWrongChr; - }; - }; - P.inOut->logMain <<"Inserted consensus variants: " << nInserted <<", including reference N-base:"<< nRefN <<", wrong chromosome: " << nWrongChr<< ", wrong reference base: " << nWrongRef << endl; - }; + //consensusSequence(); //replace with consensus allele DEPRECATED + + SjdbClass sjdbLoci; //will be filled in transcriptGeneSJ below + GTF mainGTF(*this, P, pGe.gDir, sjdbLoci); //this loads exonLoci and gene/transcript metadata only, sjdbLoci is not filled + + Genome::transformGenome(&mainGTF); + + mainGTF.superTranscript(); //this may change the genome into (Super)Transcriptome - uint N = nGenomeReal; - nGenome=N; - uint N2 = N*2; + chrBinFill();//chrBin is first used in the transcriptGeneSJ below + mainGTF.transcriptGeneSJ(pGe.gDir); + + sjdbLoadFromFiles(P,sjdbLoci);//this will not be transformed. TODO prevent this parameter combination - if (pGe.gSAindexNbases > log2(nGenome)/2-1) { + if (pGe.gSAindexNbases > log2(nGenomeTrue)/2-1) { ostringstream warnOut; - warnOut << "--genomeSAindexNbases " << pGe.gSAindexNbases << " is too large for the genome size=" << nGenome; - warnOut << ", which may cause seg-fault at the mapping step. Re-run genome generation with recommended --genomeSAindexNbases " << int(log2(nGenome)/2-1); + warnOut << "--genomeSAindexNbases " << pGe.gSAindexNbases << " is too large for the genome size=" << nGenomeTrue; + warnOut << ", which may cause seg-fault at the mapping step. Re-run genome generation with recommended --genomeSAindexNbases " << int(log2(nGenomeTrue)/2-1); warningMessage(warnOut.str(),P.inOut->logMain,std::cerr,P); - }; + }; - ofstream & chrN = ofstrOpen(pGe.gDir+"/chrName.txt",ERROR_OUT, P); - ofstream & chrS = ofstrOpen(pGe.gDir+"/chrStart.txt",ERROR_OUT, P); - ofstream & chrL = ofstrOpen(pGe.gDir+"/chrLength.txt",ERROR_OUT, P); - ofstream & chrNL = ofstrOpen(pGe.gDir+"/chrNameLength.txt",ERROR_OUT, P); - - for (uint ii=0;iilogMain, EXIT_CODE_INPUT_FILES, P); - }; + //output genome metadata + writeChrInfo(pGe.gDir); //preparing to generate SA - for (uint ii=0;ii5) + // cerr << ii <<" "<< G[ii]<<"\n"; + G[2*nGenome-1-ii]=G[ii]<4 ? 3-G[ii] : G[ii]; + }; nSA=0; - for (uint ii=0;iilogMain <<"Estimated genome size="<logMain <<"Estimated genome size with padding and SJs: total=genome+SJ="<logMain << "GstrandBit=" << int(GstrandBit) <<"\n"; - GstrandMask = ~(1LLU<1) saChunkSize=min(saChunkSize,nSA/(P.runThreadN-1)); - - uint saChunkN=nSA/saChunkSize;//estimate + uint saChunkN = nSA / saChunkSize + 1;//estimate uint* indPrefStart = new uint [saChunkN*2]; //start and stop, *2 just in case uint* indPrefChunkCount = new uint [saChunkN*2]; indPrefStart[0]=0; @@ -323,7 +263,7 @@ void Genome::genomeGenerate() { #pragma omp parallel for num_threads(P.runThreadN) ordered schedule(dynamic,1) for (int iChunk=0; iChunk < (int) saChunkN; iChunk++) {//start the chunk cycle: sort each chunk with qsort and write to a file uint* saChunk=new uint [indPrefChunkCount[iChunk]];//allocate local array for each chunk - for (uint ii=0,jj=0;ii=indPrefStart[iChunk] && p1logMain << timeMonthDayTime(rawTime) <<" ... finished generating suffix array\n" <logStdOut << timeMonthDayTime(rawTime) <<" ... finished generating suffix array\n" <logMain << timeMonthDayTime(rawTime) <<" ... writing Genome to disk ...\n" <logStdOut << timeMonthDayTime(rawTime) <<" ... writing Genome to disk ...\n" <logMain << timeMonthDayTime(rawTime) << " ..... finished successfully\n" <logStdOut << timeMonthDayTime(rawTime) << " ..... finished successfully\n" <logStdOut) << timeMonthDayTime(rawtime) << " ..... loading genome\n" <logMain << "Reading genome generation parameters:\n"; + + //read genome internal parameters + while (parFile.good()) { + string word1; + parFile >> word1; + if (word1=="###") { + parFile >> word1; + if (word1=="GstrandBit") { + uint gsb1=0; + parFile >> gsb1; + GstrandBit=(uint8) gsb1; + P.inOut->logMain << "### GstrandBit=" << (uint) GstrandBit <<"\n"; + } else { + P.inOut->logMain << "### " <logMain <logMain, EXIT_CODE_GENOME_FILES, P); + }; + + //check genome version + if (P1.versionGenome.size()==0) {// + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR: read no value for the versionGenome parameter from genomeParameters.txt file\n"; + errOut << "SOLUTION: please re-generate genome from scratch with the latest version of STAR\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); + } else if (P1.versionGenome == P.versionGenome) {// + P.inOut->logMain << "Genome version is compatible with current STAR\n"; + } else { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR: Genome version: " << P1.versionGenome << " is INCOMPATIBLE with running STAR version: "<< STAR_VERSION <<"\n"; + errOut << "SOLUTION: please re-generate genome from scratch with running version of STAR, or with version: " << P.versionGenome <<"\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); + }; + + //find chr starts from files + chrInfoLoad(); + + //check if sjdbInfo.txt exists => genome was generated with junctions + bool sjdbInfoExists=false; + struct stat sjdb1; + if ( stat( (pGe.gDir+"/sjdbInfo.txt").c_str(), &sjdb1) == 0 ) {//file exists + sjdbInfoExists=true; + }; + + if ( P.sjdbInsert.yes && sjdbInfoExists && P1.pGe.sjdbInsertSave=="") { + //if sjdbInsert, and genome had junctions, and genome is old - it should be re-generated with new STAR + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR: old Genome is INCOMPATIBLE with on the fly junction insertion\n"; + errOut << "SOLUTION: please re-generate genome from scratch with the latest version of STAR\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); + }; + + //record required genome parameters in P + pGe.gSAindexNbases=P1.pGe.gSAindexNbases; + pGe.gChrBinNbits=P1.pGe.gChrBinNbits; + genomeChrBinNbases=1LLU<0){//genomeFileSize was recorded in the genomeParameters file, copy the values to P + pGe.gFileSizes = P1.pGe.gFileSizes; + }; + + if (P.parArray.at(pGe.sjdbOverhang_par)->inputLevel==0 && P1.pGe.sjdbOverhang>0) { + //if --sjdbOverhang was not defined by user and it was defined >0 at the genome generation step, then use pGe.sjdbOverhang from the genome generation step + pGe.sjdbOverhang=P1.pGe.sjdbOverhang; + P.inOut->logMain << "--sjdbOverhang = " << pGe.sjdbOverhang << " taken from the generated genome\n"; + } else if (sjdbInfoExists && P.parArray.at(pGe.sjdbOverhang_par)->inputLevel>0 && pGe.sjdbOverhang!=P1.pGe.sjdbOverhang) { + //if pGe.sjdbOverhang was defined at the genome generation step,the mapping step value has to agree with it + ostringstream errOut; + errOut << "EXITING because of fatal PARAMETERS error: present --sjdbOverhang="<logMain, EXIT_CODE_GENOME_FILES, P); + }; + sjdbOverhang = pGe.sjdbOverhang; + sjdbLength = pGe.sjdbOverhang==0 ? 0 : pGe.sjdbOverhang*2+1; + + pGe.gType=1; + if (P1.pGe.gTypeString=="SuperTranscriptome") + pGe.gType=101; + + P.inOut->logMain << "Started loading the genome: " << asctime (localtime ( &rawtime ))<<"\n"<logMain << "Read from SAindex: pGe.gSAindexNbases=" << pGe.gSAindexNbases <<" nSAi="<< nSAi <logMain << "nGenome=" << nGenome << "; nSAbyte=" << nSAbyte <logMain <<"GstrandBit="<SetErrorStream(P.inOut->logStdOut); + + if (!sharedMemory->NeedsAllocation()) + P.inOut->logMain <<"Found genome in shared memory\n"<NeedsAllocation()) {//did not find genome in shared memory, nothing to kill + ostringstream errOut; + errOut << "EXITING: Did not find the genome in memory, did not remove any genomes from shared memory\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_GENOME_FILES, P); + } else { + sharedMemory->Clean(); + P.inOut->logMain <<"DONE: removed the genome from shared memory\n"<NeedsAllocation()){ + P.inOut->logMain <<"Allocating shared memory for genome\n"<Allocate(shmSize); + }; + } catch (const SharedMemoryException & exc){ + HandleSharedMemoryException(exc, shmSize); + }; + + shmStart = (char*) sharedMemory->GetMapped(); + shmNG= (uint*) (shmStart+SHM_sizeG); + shmNSA= (uint*) (shmStart+SHM_sizeSA); + + if (!sharedMemory->IsAllocator()) { + // genome is in shared memory or being loaded + // wait for the process that will populate it + // and record the sizes + uint iwait=0; + while (*shmNG != nGenome) { + iwait++; + P.inOut->logMain <<"Another job is still loading the genome, sleeping for 1 min\n" <logMain, EXIT_CODE_GENOME_LOADING_WAITED_TOO_LONG, P); + }; + }; + if (nSAbyte!=*shmNSA){ + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR: the SA file size did not match what we found in shared memory" << "\n" << flush; + errOut << "SOLUTION: remove the shared memory chunk by running STAR with --genomeLoad Remove, and restart STAR" << flush; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INCONSISTENT_DATA, P); + }; + P.inOut->logMain << "Using shared memory for genome. key=0x" <logMain <<"Shared memory is not used for genomes. Allocated a private copy of the genome.\n"<logMain, EXIT_CODE_MEMORY_ALLOCATION, P); + }; + }; + + G=G1+L; + + bool isAllocatorProcess = sharedMemory != NULL && sharedMemory->IsAllocator(); + + if (pGe.gLoad=="NoSharedMemory" || isAllocatorProcess) {//load genome and SAs from files + //load genome + P.inOut->logMain <<"Genome file size: "<logMain <<"Loading Genome ... " << flush; + uint64 genomeReadBytesN=fstreamReadBig(GenomeIn,G,nGenome); + P.inOut->logMain <<"done! state: good=" <logMain <<"SA file size: "<logMain <<"Loading SA ... " << flush; + genomeReadBytesN=fstreamReadBig(SAin,SA.charArray, SA.lengthByte); + P.inOut->logMain <<"done! state: good=" <logMain <<"Loading SAindex ... " << flush; + SAiInBytes +=fstreamReadBig(SAiIn,SAi.charArray, SAi.lengthByte); + P.inOut->logMain <<"done: "<logMain << "Finished loading the genome: " << asctime (localtime ( &rawtime )) <<"\n"<logMain << "Sum of all Genome bytes: " <logMain << "Sum of all SA bytes: " <logMain << "Sum of all SAi bytes: " <logMain << "pGe.gLoad=LoadAndExit: completed, the genome is loaded and kept in RAM, EXITING now.\n"<logMain << "alignIntronMax=alignMatesGapMax=0, the max intron size will be approximately determined by (2^winBinNbits)*winAnchorDistNbins=" \ + << (1LLU<0 but alignMatesGapMax==0, winBinNbits will be defined by alignIntronMax + P.inOut->logMain << "To accommodate alignIntronMax="< " << "pGe.gChrBinNbits=" << pGe.gChrBinNbits << " redefining:\n"; + P.winBinNbits=pGe.gChrBinNbits; + P.inOut->logMain << "winBinNbits=" <logMain << "To accommodate alignIntronMax="<genomeOut=genomeOut; + genomeOut.g->genomeOutLoad(); + + //debug checks +// for (auto &b : genomeOut.g->genomeOut.convBlocks) { +// uint64 g1=*(genomeOut.g->G+b[2]); +// uint64 g2=*(G+b[0]); +// if (g1!=g2) +// cout <logMain, EXIT_CODE_MEMORY_ALLOCATION, P); + + } else {//transform genome coordinates + //genomeOut + P.pGeOut.gDir=pGe.gDir+"/OriginalGenome/"; + genomeOut.convYes=true; + genomeOut.gapsAreJunctions=false; + genomeOut.convFile=pGe.gDir+"/transformGenomeBlocks.tsv"; + + + genomeOut.g = new Genome(P,P.pGeOut); + genomeOut.g->genomeOut=genomeOut; + genomeOut.g->genomeOutLoad(); + }; + }; + + if (P.pGe.gLoad=="LoadAndExit" || P.pGe.gLoad=="Remove") { + exit(0); + }; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +void Genome::loadSJDB(string &genDir) +{ + //splice junctions database + if (nGenome==chrStart[nChrReal]) {//no sjdb + sjdbN=0; + sjGstart=chrStart[nChrReal]+1; //not sure why I need that + } else {//there are sjdb chromosomes + ifstream sjdbInfo((genDir+"/sjdbInfo.txt").c_str()); + if (sjdbInfo.fail()) { + ostringstream errOut; + errOut << "EXITING because of FATAL error, could not open file " << (genDir+"/sjdbInfo.txt") <<"\n"; + errOut << "SOLUTION: check that the path to genome files, specified in --genomeDir is correct and the files are present, and have user read permsissions\n" <logMain, EXIT_CODE_INPUT_FILES, P); + }; + + + sjdbInfo >> sjdbN >> pGe.sjdbOverhang; + P.inOut->logMain << "Processing splice junctions database sjdbN=" <> sjdbStart[ii] >> sjdbEnd[ii] >> d1 >> d2 >> d3 >> d4; + sjdbMotif[ii] = (uint8) d1; + sjdbShiftLeft[ii] = (uint8) d2; + sjdbShiftRight[ii] = (uint8) d3; + sjdbStrand[ii] = (uint8) d4; + }; + sjDstart[ii] = sjdbStart[ii] - pGe.sjdbOverhang; + sjAstart[ii] = sjdbEnd[ii] + 1; + if (sjdbMotif[ii]==0) {//shinon-canonical junctions back to their true coordinates + sjDstart[ii] += sjdbShiftLeft[ii]; + sjAstart[ii] += sjdbShiftLeft[ii]; + }; + }; + }; +}; \ No newline at end of file diff --git a/source/Genome_genomeOutLoad.cpp b/source/Genome_genomeOutLoad.cpp new file mode 100755 index 00000000..eabc9be7 --- /dev/null +++ b/source/Genome_genomeOutLoad.cpp @@ -0,0 +1,58 @@ +#include "Genome.h" +#include "SuffixArrayFuns.h" +#include "PackedArray.h" +#include "ErrorWarning.h" +#include "streamFuns.h" + + +void Genome::genomeOutLoad(){//allocate and load *output* Genome + + Parameters P1; + + ifstream parFile((pGe.gDir+("/genomeParameters.txt")).c_str()); + if (parFile.good()) { + P.inOut->logMain << "Reading output genome generation parameters:\n"; + P1.inOut = P.inOut; + P1.scanAllLines(parFile,3,-1); + parFile.close(); + } else { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR: could not open genome file "<< pGe.gDir+("/genomeParameters.txt") << endl; + errOut << "SOLUTION: check that the path to genome files, specified in --genomeDir is correct and the files are present, and have user read permsissions\n" <logMain, EXIT_CODE_GENOME_FILES, P); + }; + + //find chr starts from files + chrInfoLoad(); + + + ifstream GenomeIn; + nGenome = OpenStream("Genome", GenomeIn, 0); + G=new char[nGenome]; + //uint64 genomeReadBytesN = + fstreamReadBig(GenomeIn,G,nGenome); + GenomeIn.close(); + + Genome::loadSJDB(pGe.gDir); + + //record required genome parameters in P + pGe.gSAindexNbases=P1.pGe.gSAindexNbases; + pGe.gChrBinNbits=P1.pGe.gChrBinNbits; + genomeChrBinNbases=1LLU<> nconv >> genomeOut.nMinusStrandOffset; + genomeOut.convBlocks.resize(nconv+1); + for (uint32 ii=0; ii> genomeOut.convBlocks[ii][0] >> genomeOut.convBlocks[ii][1] >> genomeOut.convBlocks[ii][2]; + + //genomeOut.convBlocks[nconv][0]=genomeOut.convBlocks[nconv-1][0]+genomeOut.convBlocks[nconv-1][1]; + genomeOut.convBlocks[nconv-1][1] +=1;//increase the length of the last block so that we never reach the last base + genomeOut.convBlocks[nconv][0]=(uint64)-1;//start of the block after last is infinity +}; diff --git a/source/Genome_transformGenome.cpp b/source/Genome_transformGenome.cpp new file mode 100755 index 00000000..fdba9261 --- /dev/null +++ b/source/Genome_transformGenome.cpp @@ -0,0 +1,323 @@ +#include "Genome.h" +#include "SequenceFuns.h" +#include "streamFuns.h" +#include "ErrorWarning.h" +#include "serviceFuns.cpp" +#include "GTF.h" + +template +void appendVector(vector &v1, const vector &v2) +{ + v1.reserve(v1.size()+v2.size()); + v1.insert(v1.end(), v2.begin(), v2.end()); +}; + +template +vector concatenateVectors(const vector &v1, const vector &v2) +{ + vector vOut; + vOut.reserve(v1.size()+v2.size()); + vOut=v1; + vOut.insert(vOut.end(), v2.begin(), v2.end()); + return vOut; +}; + +vector appendString (vector vString, string strAdd) +{ + for (auto & s : vString) + s += strAdd; + return vString; +}; + +void Genome::transformGenome(GTF *gtf) +{ + if (pGe.transform.type==0) + return; + + P.inOut->logMain << "transformGenome: processing VCF" << endl; + + map> vcfVariants[pGe.transform.type]; + {//load VCF file: per chromosome, 1 or 2 haplotypes + ifstream &vcfStream = ifstrOpen(pGe.transform.vcfFile, ERROR_OUT, "SOLUTION: check the path and permissions of the VCF file: "+pGe.transform.vcfFile, P); + string vcfLine; + while (std::getline (vcfStream, vcfLine)) { + string chr,id, ref, alt, dummy, sample; + uint64 pos; + + istringstream vcfLineStream(vcfLine); + vcfLineStream >> chr; + + if (chr.at(0)=='#') + continue; + if (chrNameIndex.count(chr)==0) {//chr not in Genome + P.inOut->logMain << "WARNING: while processing varVCFfile file=" << P.var.vcfFile <<": chromosome '"<logMain << "WARNING: VCF: * allele"<> pos >> id >> ref >> alt >> dummy >> dummy >> dummy >> dummy >> sample; + //we assume ref can only be one sequence + + vector altV; + splitString(alt,',',altV); + + if (pGe.transform.type==1) {//use first alt allele TODO make warning if there are 2 alts? + alt=altV[0]; + VariantInfo var1={pos, (int32)alt.size()-(int32)ref.size(), {ref,alt}}; + vcfVariants[0][chr].push_back(var1); + } else if (pGe.transform.type==2) {//diploid genome + for (uint32 ih=0; ih<2; ih++) { + //TODO check that sample has proper format (i.e. 0|1 or 0/1 etc) + int32 gt=atoi(&sample.at(ih*2)); //process genotype info in the form of 0|1, i.e. 0th char and 2nd char + + if (gt==0) //ref haplotype - do not record + continue; + + alt=altV[gt-1];//select alt + VariantInfo var1={pos, (int32)alt.size()-(int32)ref.size(), {ref,alt}}; + vcfVariants[ih][chr].push_back(var1); + }; + }; + }; + vcfStream.close(); + }; + + uint64 nGenome1=0, nG1allocNew; + char *Gnew=NULL, *G1new=NULL; + + if (pGe.transform.type==1) {//haploid: insert alternative alleles into genome sequence, create conversion-block file + vector chrStart1, chrLength1; + transformChrLenStart(vcfVariants[0], chrStart1, chrLength1); + + nGenome1=chrStart1.back(); + P.inOut->logMain << "Old/new genome sizes: " << nGenome <<" "<< nGenome1 <> transformBlocks; + transformGandBlocks(vcfVariants[0], chrStart1, chrLength1, transformBlocks, Gnew); + transformExonLoci(gtf->exonLoci, transformBlocks); + + chrStart=chrStart1; + chrLength=chrLength1; + + transformBlocksWrite(transformBlocks); + + } else if (pGe.transform.type==2) {//diploid: duplicate chromosomes, insert genotypes into sequence + + vector chrStart1[2], chrLength1[2]; + for (uint32 ih=0; ih<2; ih++) + transformChrLenStart(vcfVariants[ih], chrStart1[ih], chrLength1[ih]); + + for (auto &cs : chrStart1[1]) + cs += chrStart1[0].back(); + + nGenome1=chrStart1[1].back(); + P.inOut->logMain << "Old/new genome sizes: " << nGenome <<" "<< nGenome1 <> transformBlocks[2]; + transformGandBlocks(vcfVariants[0], chrStart1[0], chrLength1[0], transformBlocks[0], Gnew);//fill first haplotype sequence + transformGandBlocks(vcfVariants[1], chrStart1[1], chrLength1[1], transformBlocks[1], Gnew);//fill second haplotype sequence + + //annotations + vector> exonLoci1[2]; + exonLoci1[0]=gtf->exonLoci; + exonLoci1[1]=gtf->exonLoci; + for (auto & exon : exonLoci1[1]) {//shift gene/tanscript IDs for 2nd haplotype + exon[exT] += gtf->transcriptID.size(); + exon[exG] += gtf->geneID.size(); + }; + + appendVector(gtf->geneAttr, gtf->geneAttr); + appendVector(gtf->transcriptStrand, gtf->transcriptStrand); + gtf->geneID = concatenateVectors(appendString(gtf->geneID, "_h1"), appendString(gtf->geneID, "_h2")); + gtf->transcriptID = concatenateVectors(appendString(gtf->transcriptID, "_h1"), appendString(gtf->transcriptID, "_h2")); + + transformExonLoci(exonLoci1[0], transformBlocks[0]); + transformExonLoci(exonLoci1[1], transformBlocks[1]); + + //concatenate all vectors + chrName = concatenateVectors( appendString(chrName, "_h1"), appendString(chrName, "_h2") ); + nChrReal=chrName.size(); + + for (uint ii=0;iiexonLoci=concatenateVectors( exonLoci1[0], exonLoci1[1] ); + + appendVector( transformBlocks[0], transformBlocks[1] ); + transformBlocksWrite(transformBlocks[0]); + }; + + //assign transformed genome + delete[] G1; + G1=G1new; + G=Gnew; + nG1alloc=nG1allocNew; + nGenome=nGenome1; +}; + +void Genome::transformChrLenStart(map> &vcfVariants, vector &chrStart1, vector &chrLength1) +{//recalculate chrLength/Start + chrStart1=chrStart; + chrLength1=chrLength; + //vector chrTransformYes(chrLength.size(), false); + for (uint32 ichr=0; ichr &vV = vcfVariants[chrName[ichr]]; + + std::sort(vV.begin(), vV.end(), + [](const VariantInfo &vi1, const VariantInfo &vi2) { + return vi1.pos < vi2.pos; + }); + + //filter: remove variants overlapping deletions + vector vV1; + vV1.reserve(vV.size()); + uint64 g0=0; //first base after variant + for (const auto &v : vV) { + if (v.pos>=g0) + vV1.push_back(v); + g0=max(g0,v.pos+v.seq[0].size()); + }; + P.inOut->logMain << chrName[ichr] <<": filtered out overlapping variants = "<< (int64)vV.size()-(int64)vV1.size() <<"; remaining variants = "<< vV1.size() <<'\n'; + vV=vV1; + + for (const auto &v : vV) { + chrLength1[ichr] += (int64)v.seq[1].size()-(int64)v.seq[0].size(); + }; + P.inOut->logMain << "Transformed chr length difference: " <logMain << "Transformed chr start difference: " << chrName[ichr] <<" "<< chrStart1[ichr]-chrStart[ichr] <<'\n'; + }; +}; + +void Genome::transformGandBlocks(map> &vcfVariants, vector &chrStart1, vector &chrLength1, vector> &transformBlocks, char *Gnew) +{ + for (uint32 ichr=0; ichr &vV = vcfVariants[chrName[ichr]]; + + uint64 iv=0, g1=chrStart1[ichr], g0=chrStart[ichr]; + transformBlocks.push_back({g0, 0, g1});//first block for the chromosome + while (g0 &seq = vV[iv].seq; + + //debug + char s0[seq[0].size()]; + convertNucleotidesToNumbers(seq[0].c_str(), s0, seq[0].size()); + if (memcmp(G+g0, s0, seq[0].size())) + cerr <> &transformBlocks) +{//write out transformBlocks + ofstream & convStream = ofstrOpen(P.pGe.gDir+"/transformGenomeBlocks.tsv",ERROR_OUT, P); + convStream << transformBlocks.size() <<'\t'<< "-1" <<'\n'; //no -strand + + for (auto &tb : transformBlocks) { + convStream << tb[2] <<'\t'<< tb[1] <<'\t'<< tb[0] <<'\n'; //revert old new for reverse conversion + }; + convStream.close(); +}; + +void Genome::transformExonLoci(vector> &exonLoci, vector> &transformBlocks) +{//transform exonLoci with transformBlocks + //simple point transformation for start and end + //start in the gap moves to the right, end in the gap moves to the left + auto exonLoci1(exonLoci); + exonLoci1.clear(); + for (auto & exon : exonLoci) { + + auto exonS = exon[exS]; + auto exonE = exon[exE]; + auto tBit = std::upper_bound(transformBlocks.begin(), transformBlocks.end(), array {exonS,0,0}, + [](const array &t1, const array &t2) + { + return t1[0] < t2[0]; + }); + + --tBit; //tBit is last block start on the left of exonS + auto tB=*tBit; + + if (exonS < tB[0]+tB[1]) {//exonS inside block + exon[exS]=tB[2]+exonS-tB[0]; + } else { + exon[exS]=tBit[1][2];//exon start shifts to the next block + }; + + while ( exonE > (*tBit)[0]+(*tBit)[1] ) //until exonE is not past the end of the block + ++tBit; + + tB=*tBit; + if (exonE >= tB[0]) {//exonE inside block + exon[exE]=tB[2]+exonE-tB[0]; + } else { + exon[exE]=tBit[-1][2]+tBit[-1][1]-1;//exon end shifts to the end of the previous block + }; + + if (exon[exS]<=exon[exE]) + exonLoci1.push_back(exon); + }; + + P.inOut->logMain << "Transform exons: removed " << exonLoci.size()- exonLoci1.size() < #include #include +#include +#include #include "VERSION" @@ -68,12 +70,10 @@ typedef uint8_t uint8; #define scoreMatch 1 - //cleaned //output #define BAMoutput_oneAlignMaxBytes 100000 - //SAM attributes #define ATTR_NH 1 #define ATTR_HI 2 @@ -95,6 +95,17 @@ typedef uint8_t uint8; #define ATTR_CY 18 #define ATTR_UR 19 #define ATTR_UY 20 +#define ATTR_CB 21 +#define ATTR_UB 22 +#define ATTR_GX 23 +#define ATTR_GN 24 +#define ATTR_sM 25 +#define ATTR_sS 26 +#define ATTR_sQ 27 +#define ATTR_ha 28 +#define ATTR_cN 29 +#define ATTR_gx 30 +#define ATTR_gn 31 //BAM definitions #define BAM_CIGAR_MaxSize 10000 @@ -110,16 +121,17 @@ typedef uint8_t uint8; #define BAM_CIGAR_X 8 + +#define BAM_ATTR_MaxSize 10000 + #if defined COMPILE_FOR_LONG_READS #define MAX_N_EXONS 1000 - #define BAM_ATTR_MaxSize 10000 #else #define MAX_N_EXONS 20 - #define BAM_ATTR_MaxSize 1000 #endif //input reads -#define MAX_N_MATES 2 +#define MAX_N_MATES 3 #define DEF_readNameLengthMax 50000 #if defined COMPILE_FOR_LONG_READS #define DEF_readSeqLengthMax 500000 @@ -144,6 +156,7 @@ typedef uint8_t uint8; #define EXIT_CODE_FILE_OPEN 109 #define EXIT_CODE_FILE_WRITE 110 #define EXIT_CODE_INCONSISTENT_DATA 111 +#define EXIT_CODE_FIFO 112 //cleaned-end diff --git a/source/Makefile b/source/Makefile index 8e340746..15b76979 100644 --- a/source/Makefile +++ b/source/Makefile @@ -1,4 +1,4 @@ -# user may define these whole flags +# user may define the whole sets of flags # LDFLAGS # CPPFLAGS # CXXFLAGS @@ -13,29 +13,61 @@ CXX ?= g++ # pre-defined flags LDFLAGS_shared := -pthread -Lhtslib -Bstatic -lhts -Bdynamic -lz -LDFLAGS_static := -static -static-libgcc -pthread -Lhtslib -lhts -lz +LDFLAGS_static := -static -static-libgcc -pthread -Lhtslib -lhts -lz LDFLAGS_Mac :=-pthread -lz htslib/libhts.a LDFLAGS_Mac_static :=-pthread -lz -static-libgcc htslib/libhts.a LDFLAGS_gdb := $(LDFLAGS_shared) -COMPTIMEPLACE := -D'COMPILATION_TIME_PLACE="$(shell echo `date` $(HOSTNAME):`pwd`)"' +DATE_FMT = --iso-8601=seconds +ifdef SOURCE_DATE_EPOCH + BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u "$(DATE_FMT)") +else + BUILD_DATE ?= $(shell date "$(DATE_FMT)") +endif -CXXFLAGS_common := -pipe -std=c++11 -Wall -Wextra -fopenmp $(COMPTIMEPLACE) -CXXFLAGS_main := -O3 $(CXXFLAGS_common) -CXXFLAGS_gdb := -O0 -g $(CXXFLAGS_common) +BUILD_PLACE ?= $(HOSTNAME):$(shell pwd) -CFLAGS := -O3 -pipe -Wall -Wextra $(CFLAGS) +COMPTIMEPLACE := -D'COMPILATION_TIME_PLACE="$(BUILD_DATE) $(BUILD_PLACE)"' -########################################################################################################## +GIT_CHECK := $(shell git status 1> /dev/null 2> /dev/null && echo 0) +ifeq ($(GIT_CHECK),0) + GIT_DIFF := $(shell git diff --name-only | tr '\n' ' ') + GIT_BRANCH_COMMIT_DIFF := $(shell git status | head -n 1) ; \ + $(shell git log | head -n 1) ; \ + diff files: $(GIT_DIFF) +endif +GIT_BRANCH_COMMIT_DIFF := -D'GIT_BRANCH_COMMIT_DIFF="$(GIT_BRANCH_COMMIT_DIFF)"' -OBJECTS = ParametersChimeric_initialize.o ParametersSolo.o SoloRead.o SoloRead_record.o \ - SoloReadBarcode.o SoloReadBarcode_getCBandUMI.o \ +# Defaults, can be overridden by make arguments or environment +CXXFLAGS ?= -pipe -Wall -Wextra +CFLAGS ?= -pipe -Wall -Wextra -O3 +CXXFLAGS_SIMD ?= -mavx2 + +# Unconditionally set essential flags and optimization options +CXXFLAGS_common := -std=c++11 -fopenmp $(COMPTIMEPLACE) $(GIT_BRANCH_COMMIT_DIFF) +CXXFLAGS_main := -O3 $(CXXFLAGS_common) +CXXFLAGS_gdb := -O0 -g3 $(CXXFLAGS_common) + +########################################################################################################## +OBJECTS = SoloFeature_collapseUMI_Graph.o SoloFeature_collapseUMIall_multiMappers.o ParametersClip_initialize.o ClipMate_clip.o ClipCR4.o opal/opal.o ClipMate_clipChunk.o ClipMate_initialize.o \ + SoloFeature_loadRawMatrix.o SoloFeature_emptyDrops_CR.o soloInputFeatureUMI.o SoloFeature_countSmartSeq.o SoloFeature_redistributeReadsByCB.o \ + SoloFeature_quantTranscript.o SoloFeature_sumThreads.o SoloFeature_countVelocyto.o SoloFeature_countCBgeneUMI.o \ + Transcriptome_classifyAlign.o Transcriptome_geneFullAlignOverlap_ExonOverIntron.o Transcriptome_alignExonOverlap.cpp \ + SoloFeature_cellFiltering.o \ + SoloFeature_statsOutput.o bamSortByCoordinate.o SoloBarcode.o \ + ParametersSolo.o SoloRead.o SoloRead_record.o \ + SoloReadBarcode.o SoloReadBarcode_getCBandUMI.o SoloBarcode_extractBarcode.o \ SoloReadFeature.o SoloReadFeature_record.o SoloReadFeature_inputRecords.o \ - Solo.o SoloFeature.o SoloFeature_collapseUMI.o SoloFeature_outputResults.o SoloFeature_processRecords.o\ + Solo.o SoloFeature.o SoloFeature_outputResults.o SoloFeature_processRecords.o SoloFeature_addBAMtags.o \ + ReadAlign_transformGenome.o Genome_transformGenome.o Transcript_convertGenomeCigar.o \ + twoPassRunPass1.o samHeaders.o Genome_genomeLoad.o Genome_genomeOutLoad.o Transcript_transformGenome.o ReadAlign_outputSpliceGraphSAM.o \ + ReadAlign_mapOneReadSpliceGraph.o SpliceGraph.o SpliceGraph_swScoreSpliced.o SpliceGraph_swTraceBack.o \ + SpliceGraph_findSuperTr.o sjAlignSplit.o \ + GTF.o GTF_transcriptGeneSJ.o GTF_superTranscript.o SuperTranscriptome.o \ ReadAlign_outputAlignments.o \ ReadAlign.o STAR.o \ - SharedMemory.o PackedArray.o SuffixArrayFuns.o Parameters.o InOutStreams.o SequenceFuns.o Genome.o Stats.o \ + SharedMemory.o PackedArray.o SuffixArrayFuns.o Parameters.o Parameters_samAttributes.o InOutStreams.o SequenceFuns.o Genome.o ParametersGenome.o Stats.o \ Transcript.o Transcript_alignScore.o Transcript_generateCigarP.o Chain.o \ Transcript_variationAdjust.o Variation.o ReadAlign_waspMap.o \ ReadAlign_storeAligns.o ReadAlign_stitchPieces.o ReadAlign_multMapSelect.o ReadAlign_mapOneRead.o readLoad.o \ @@ -46,19 +78,19 @@ OBJECTS = ParametersChimeric_initialize.o ParametersSolo.o SoloRead.o SoloRead_r ReadAlign_createExtendWindowsWithAlign.o ReadAlign_assignAlignToWindow.o ReadAlign_oneRead.o \ ReadAlign_stitchWindowSeeds.o \ ReadAlign_peOverlapMergeMap.o ReadAlign_mappedFilter.o \ - ReadAlign_chimericDetection.o ReadAlign_chimericDetectionOld.o ReadAlign_chimericDetectionOldOutput.o\ + ParametersChimeric_initialize.o ReadAlign_chimericDetection.o ReadAlign_chimericDetectionOld.o ReadAlign_chimericDetectionOldOutput.o\ ChimericDetection.o ChimericDetection_chimericDetectionMult.o ReadAlign_chimericDetectionPEmerged.o \ - ChimericSegment.cpp ChimericAlign.cpp ChimericAlign_chimericJunctionOutput.o ChimericAlign_chimericStitching.o \ - stitchWindowAligns.o extendAlign.o stitchAlignToTranscript.o alignSmithWaterman.o \ + stitchWindowAligns.o extendAlign.o stitchAlignToTranscript.o \ + ChimericSegment.cpp ChimericAlign.cpp ChimericAlign_chimericJunctionOutput.o ChimericAlign_chimericBAMoutput.o ChimericAlign_chimericStitching.o \ Genome_genomeGenerate.o genomeParametersWrite.o genomeScanFastaFiles.o genomeSAindex.o \ Genome_insertSequences.o insertSeqSA.o funCompareUintAndSuffixes.o funCompareUintAndSuffixesMemcmp.o \ - TimeFunctions.o ErrorWarning.o loadGTF.o streamFuns.o stringSubstituteAll.o \ + TimeFunctions.o ErrorWarning.o streamFuns.o stringSubstituteAll.o \ Transcriptome.o Transcriptome_quantAlign.o Transcriptome_geneFullAlignOverlap.o \ ReadAlign_quantTranscriptome.o Quantifications.o Transcriptome_geneCountsAddAlign.o \ sjdbLoadFromFiles.o sjdbLoadFromStream.o sjdbPrepare.o sjdbBuildIndex.o sjdbInsertJunctions.o mapThreadsSpawn.o \ - Parameters_openReadsFiles.cpp Parameters_closeReadsFiles.cpp Parameters_readSAMheader.o \ + Parameters_readFilesInit.o Parameters_openReadsFiles.cpp Parameters_closeReadsFiles.cpp Parameters_readSAMheader.o \ bam_cat.o serviceFuns.o GlobalVariables.cpp \ - BAMoutput.o BAMfunctions.o ReadAlign_alignBAM.o BAMbinSortByCoordinate.o signalFromBAM.o bamRemoveDuplicates.o BAMbinSortUnmapped.o + BAMoutput.o BAMfunctions.o ReadAlign_alignBAM.o BAMbinSortByCoordinate.o signalFromBAM.o bamRemoveDuplicates.o BAMbinSortUnmapped.o SOURCES := $(wildcard *.cpp) $(wildcard *.c) @@ -69,25 +101,33 @@ SOURCES := $(wildcard *.cpp) $(wildcard *.c) %.o : %.c $(CXX) -c $(CPPFLAGS) $(CFLAGS) $< -all: STAR +all: cleanCompileInfo STAR$(SFX) + +opal/opal.o : opal/opal.cpp opal/opal.h + cd opal && \ + $(CXX) -c -I./ -std=c++11 $(CPPFLAGS) $(CXXFLAGS) $(CXXFLAGSextra) $(CXXFLAGS_SIMD) opal.cpp .PHONY: clean clean: - rm -f *.o STAR STARstatic STARlong Depend.list + 'rm' -f *.o opal/opal.o STAR STARstatic STARlong Depend.list parametersDefault.xxd .PHONY: CLEAN -CLEAN: - rm -f *.o STAR Depend.list +CLEAN: clean $(MAKE) -C htslib clean -.PHONY: cleanRelease -cleanRelease: - rm -f *.o Depend.list - $(MAKE) -C htslib clean + +.PHONY: clean_solo +clean_solo: + 'rm' -f Solo*.o + +.PHONY: cleanCompileInfo +cleanCompileInfo: + 'rm' -f STAR.o Parameters.o ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),cleanRelease) ifneq ($(MAKECMDGOALS),CLEAN) +ifneq ($(MAKECMDGOALS),CLEAN) +ifneq ($(MAKECMDGOALS),clean_solo) ifneq ($(MAKECMDGOALS),STARforMac) ifneq ($(MAKECMDGOALS),STARforMacGDB) Depend.list: $(SOURCES) parametersDefault.xxd htslib @@ -100,6 +140,7 @@ endif endif endif endif +endif htslib : htslib/libhts.a @@ -109,30 +150,32 @@ htslib/libhts.a : parametersDefault.xxd: parametersDefault xxd -i parametersDefault > parametersDefault.xxd -STAR : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) $(CXXFLAGS) -STAR : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_shared) $(LDFLAGS) -STAR : Depend.list parametersDefault.xxd $(OBJECTS) - $(CXX) -o STAR $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) +STAR$(SFX) : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) $(CXXFLAGS) +STAR$(SFX) : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_shared) $(LDFLAGS) +STAR$(SFX) : Depend.list parametersDefault.xxd $(OBJECTS) + $(CXX) -o STAR$(SFX) $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) -POSIXSHARED : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) -DPOSIX_SHARED_MEM $(CXXFLAGS) -POSIXSHARED : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_shared) $(LDFLAGS) -POSIXSHARED : Depend.list parametersDefault.xxd $(OBJECTS) - $(CXX) -o STAR $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) +STARstatic$(SFX) : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) $(CXXFLAGS) +STARstatic$(SFX) : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_static) $(LDFLAGS) +STARstatic$(SFX) : Depend.list parametersDefault.xxd $(OBJECTS) + $(CXX) -o STAR$(SFX) $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) -STARstatic : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) $(CXXFLAGS) -STARstatic : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_static) $(LDFLAGS) -STARstatic : Depend.list parametersDefault.xxd $(OBJECTS) - $(CXX) -o STAR $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) +STARlong$(SFX) : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) -D'COMPILE_FOR_LONG_READS' $(CXXFLAGS) +STARlong$(SFX) : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_shared) $(LDFLAGS) +STARlong$(SFX) : Depend.list parametersDefault.xxd $(OBJECTS) + $(CXX) -o STARlong$(SFX) $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) -STARlong : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) -D'COMPILE_FOR_LONG_READS' $(CXXFLAGS) -STARlong : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_shared) $(LDFLAGS) -STARlong : Depend.list parametersDefault.xxd $(OBJECTS) - $(CXX) -o STARlong $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) +STARlongStatic$(SFX) : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) -D'COMPILE_FOR_LONG_READS' $(CXXFLAGS) +STARlongStatic$(SFX) : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_static) $(LDFLAGS) +STARlongStatic$(SFX) : Depend.list parametersDefault.xxd $(OBJECTS) + $(CXX) -o STARlong$(SFX) $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) -STARlongStatic : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) -D'COMPILE_FOR_LONG_READS' $(CXXFLAGS) -STARlongStatic : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_static) $(LDFLAGS) -STARlongStatic : Depend.list parametersDefault.xxd $(OBJECTS) - $(CXX) -o STARlong $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) + + +POSIXSHARED : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_main) -DPOSIX_SHARED_MEM $(CXXFLAGS) +POSIXSHARED : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_shared) $(LDFLAGS) +POSIXSHARED : Depend.list parametersDefault.xxd $(OBJECTS) + $(CXX) -o STAR$(SFX) $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) gdb : CXXFLAGS := $(CXXFLAGSextra) $(CXXFLAGS_gdb) $(CXXFLAGS) gdb : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_gdb) $(LDFLAGS) @@ -153,5 +196,3 @@ STARlongForMacStatic : CXXFLAGS := -D'COMPILE_FOR_LONG_READS' $(CXXFLAGSextra) $ STARlongForMacStatic : LDFLAGS := $(LDFLAGSextra) $(LDFLAGS_Mac_static) $(LDFLAGS) STARlongForMacStatic : Depend.list parametersDefault.xxd $(OBJECTS) $(CXX) -o STARlong $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) - - diff --git a/source/OutSJ.cpp b/source/OutSJ.cpp index ea01b847..f2181e2d 100644 --- a/source/OutSJ.cpp +++ b/source/OutSJ.cpp @@ -1,7 +1,7 @@ #include "OutSJ.h" #include "ErrorWarning.h" -OutSJ::OutSJ (uint nSJmax, Parameters &Pin, Genome &genomeIn) : oneSJ(genomeIn), P(Pin), mapGen(genomeIn) {//do I need P? +OutSJ::OutSJ (uint nSJmax, Parameters &Pin, Genome &genomeIn) : oneSJ(genomeIn), P(Pin), genOut(genomeIn) {//do I need P? data = new char [oneSJ.dataSize*nSJmax]; //allocate big array of SJ loci and properties memset(data,0,oneSJ.dataSize*nSJmax); @@ -56,7 +56,7 @@ void OutSJ::collapseSJ() {//collapse junctions. Simple version now: re-sort ever N=isj1+1; }; -Junction::Junction(Genome &genomeIn) : mapGen(genomeIn) { +Junction::Junction(Genome &genOut) : genOut(genOut) { }; //////////////////////////////////////////////////// oneJunctionWrite @@ -74,8 +74,8 @@ void Junction::junctionPointer(char* sjPoint, uint isj) {// }; void Junction::outputStream(ostream &outStream) { - uint sjChr=mapGen.chrBin[*start >> mapGen.pGe.gChrBinNbits]; - outStream << mapGen.chrName.at(sjChr) <<"\t"<< *start + 1 - mapGen.chrStart[sjChr] <<"\t"<<*start + *gap - mapGen.chrStart[sjChr] \ + uint sjChr=genOut.chrBin[*start >> genOut.pGe.gChrBinNbits]; + outStream << genOut.chrName.at(sjChr) <<"\t"<< *start + 1 - genOut.chrStart[sjChr] <<"\t"<<*start + *gap - genOut.chrStart[sjChr] \ <<"\t"<< int(*strand) <<"\t"<< int(*motif) <<"\t"<< int (*annot) <<"\t"<< *countUnique <<"\t"<< *countMultiple \ <<"\t"<< *overhangLeft << endl; }; @@ -85,30 +85,30 @@ void Junction::collapseOneSJ(char* isj1P, char* isjP, Parameters& P) {//collapse *(uint32*)(isj1P+countMultipleP) += *(uint32*)(isjP+countMultipleP); if (*(uint16*)(isj1P+overhangLeftP) < *(uint16*)(isjP+overhangLeftP) ) { - *(uint16*)(isj1P+overhangLeftP) = *(uint16*)(isjP+overhangLeftP) ; + *(uint16*)(isj1P+overhangLeftP) = *(uint16*)(isjP+overhangLeftP); }; if (*(uint16*)(isj1P+overhangRightP) < *(uint16*)(isjP+overhangRightP) ) { - *(uint16*)(isj1P+overhangRightP) = *(uint16*)(isjP+overhangRightP) ; + *(uint16*)(isj1P+overhangRightP) = *(uint16*)(isjP+overhangRightP); }; if (*(isj1P+motifP) != *(isjP+motifP) ) { uint s1=*(uint*)(isj1P+startP); - uint c1=mapGen.chrBin[ s1 >> mapGen.pGe.gChrBinNbits]; + uint c1=genOut.chrBin[ s1 >> genOut.pGe.gChrBinNbits]; stringstream errOut; - errOut <<"EXITING becaues of BUG: different motifs for the same junction while collapsing junctions\n" \ - << mapGen.chrName[c1] <<" "<< s1-mapGen.chrStart[c1]+1 <<" "<logMain, EXIT_CODE_BUG, P);\ -// *(isj1P+motifP) = *(isjP+motifP) ; + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); + + //*(isj1P+motifP) = *(isjP+motifP) ; }; if (*(isj1P+annotP) < *(isjP+annotP) ) { stringstream errOut; - errOut <<"EXITING becaues of BUG: different annotation status for the same junction while collapsing junctions:"\ + errOut <<"EXITING because of BUG: different annotation status for the same junction while collapsing junctions:"\ <<*(uint*)(isj1P+startP) <<" "<<*(uint32*)(isj1P+gapP) <<" "<logMain, EXIT_CODE_BUG, P);\ + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); -// *(isj1P+annotP) = *(isjP+annotP) ; + //*(isj1P+annotP) = *(isjP+annotP) ; }; - -} +}; diff --git a/source/OutSJ.h b/source/OutSJ.h index d0c9838c..aebc9036 100644 --- a/source/OutSJ.h +++ b/source/OutSJ.h @@ -30,7 +30,7 @@ class Junction {//one junction void collapseOneSJ(char* isj1P, char* isjP, Parameters& P); private: - Genome &mapGen; + Genome &genOut; }; class OutSJ { @@ -47,7 +47,7 @@ class OutSJ { private: Parameters &P; - Genome &mapGen; + Genome &genOut; }; int compareSJ(const void* i1, const void* i2); //external functions diff --git a/source/ParameterInfo.h b/source/ParameterInfo.h index cd67c6a4..39e907c2 100644 --- a/source/ParameterInfo.h +++ b/source/ParameterInfo.h @@ -5,7 +5,7 @@ class ParameterInfoBase { public: string nameString; //string that identifies parameter int inputLevel; //where the parameter was defined - int inputLevelAllowed; //at which inpurt level parameter definition is allowed + int inputLevelAllowed; //at which input level parameter definition is allowed virtual void inputValues(istringstream &streamIn) =0; friend std::ostream& operator<< (std::ostream& o, ParameterInfoBase const& b); virtual ~ParameterInfoBase() {}; diff --git a/source/Parameters.cpp b/source/Parameters.cpp index 50fbcfe7..9cba6f6a 100755 --- a/source/Parameters.cpp +++ b/source/Parameters.cpp @@ -9,6 +9,7 @@ #include "GlobalVariables.h" #include "signalFromBAM.h" #include "bamRemoveDuplicates.h" +#include "streamFuns.h" //for mkfifo #include @@ -29,12 +30,13 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "sysShell", &sysShell)); //run - parArray.push_back(new ParameterInfoScalar (-1, -1, "runMode", &runMode)); + parArray.push_back(new ParameterInfoVector (-1, -1, "runMode", &runModeIn)); parArray.push_back(new ParameterInfoScalar (-1, -1, "runThreadN", &runThreadN)); parArray.push_back(new ParameterInfoScalar (-1, -1, "runDirPerm", &runDirPermIn)); parArray.push_back(new ParameterInfoScalar (-1, -1, "runRNGseed", &runRNGseed)); //genome + parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeType", &pGe.gTypeString)); parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeDir", &pGe.gDir)); parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeLoad", &pGe.gLoad)); parArray.push_back(new ParameterInfoVector (-1, -1, "genomeFastaFiles", &pGe.gFastaFiles)); @@ -44,7 +46,10 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeSAsparseD", &pGe.gSAsparseD)); parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeSuffixLengthMax", &pGe.gSuffixLengthMax)); parArray.push_back(new ParameterInfoVector (-1, -1, "genomeFileSizes", &pGe.gFileSizes)); - parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeConsensusFile", &pGe.gConsensusFile)); + //parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeConsensusFile", &pGe.gConsensusFile)); DEPRECATED + parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeTransformType", &pGe.transform.typeString)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "genomeTransformVCF", &pGe.transform.vcfFile)); + parArray.push_back(new ParameterInfoVector (-1, -1, "genomeTransformOutput", &pGe.transform.output)); //read parArray.push_back(new ParameterInfoVector (-1, -1, "readFilesType", &readFilesType)); @@ -55,6 +60,10 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "readMatesLengthsIn", &readMatesLengthsIn)); parArray.push_back(new ParameterInfoScalar (-1, -1, "readMapNumber", &readMapNumber)); parArray.push_back(new ParameterInfoVector (-1, -1, "readNameSeparator", &readNameSeparator)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "readQualityScoreBase", &readQualityScoreBase)); + parArray.push_back(new ParameterInfoVector (-1, -1, "readFilesManifest", &readFilesManifest)); + parArray.push_back(new ParameterInfoVector (-1, -1, "readFilesSAMattrKeep", &readFiles.samAttrKeepIn)); + //parArray.push_back(new ParameterInfoScalar (-1, -1, "readStrand", &pReads.strandString)); @@ -67,7 +76,7 @@ Parameters::Parameters() {//initalize parameters info //limits parArray.push_back(new ParameterInfoScalar (-1, -1, "limitGenomeGenerateRAM", &limitGenomeGenerateRAM)); - parArray.push_back(new ParameterInfoScalar (-1, -1, "limitIObufferSize", &limitIObufferSize)); + parArray.push_back(new ParameterInfoVector (-1, -1, "limitIObufferSize", &limitIObufferSize)); parArray.push_back(new ParameterInfoScalar (-1, -1, "limitOutSAMoneReadBytes", &limitOutSAMoneReadBytes)); parArray.push_back(new ParameterInfoScalar (-1, -1, "limitOutSJcollapsed", &limitOutSJcollapsed)); parArray.push_back(new ParameterInfoScalar (-1, -1, "limitOutSJoneRead", &limitOutSJoneRead)); @@ -108,8 +117,10 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "outSAMattrIHstart", &outSAMattrIHstart)); parArray.push_back(new ParameterInfoScalar (-1, -1, "outSAMtlen", &outSAMtlen)); - - //output SJ filtering + //outSJ + parArray.push_back(new ParameterInfoVector (-1, -1, "outSJtype", &outSJ.type)); + + //output SJ filtering parArray.push_back(new ParameterInfoScalar (-1, -1, "outSJfilterReads", &outSJfilterReads)); parArray.push_back(new ParameterInfoVector (-1, -1, "outSJfilterCountUniqueMin", &outSJfilterCountUniqueMin)); parArray.push_back(new ParameterInfoVector (-1, -1, "outSJfilterCountTotalMin", &outSJfilterCountTotalMin)); @@ -142,11 +153,15 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "outFilterIntronStrands", &outFilterIntronStrands)); //clipping - parArray.push_back(new ParameterInfoVector (-1, -1, "clip5pNbases", &clip5pNbases)); - parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pNbases", &clip3pNbases)); - parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pAfterAdapterNbases", &clip3pAfterAdapterNbases)); - parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pAdapterSeq", &clip3pAdapterSeq)); - parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pAdapterMMp", &clip3pAdapterMMp)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clipAdapterType", &pClip.adapterType)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip5pNbases", &pClip.in[0].N)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pNbases", &pClip.in[1].N)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip5pAfterAdapterNbases", &pClip.in[0].NafterAd)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pAfterAdapterNbases", &pClip.in[1].NafterAd)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip5pAdapterSeq", &pClip.in[0].adSeq)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pAdapterSeq", &pClip.in[1].adSeq)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip5pAdapterMMp", &pClip.in[0].adMMp)); + parArray.push_back(new ParameterInfoVector (-1, -1, "clip3pAdapterMMp", &pClip.in[1].adMMp)); //binning, anchors, windows parArray.push_back(new ParameterInfoScalar (-1, -1, "winBinNbits", &winBinNbits)); @@ -179,7 +194,8 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "seedNoneLociPerWindow", &seedNoneLociPerWindow)); parArray.push_back(new ParameterInfoScalar (-1, -1, "seedMultimapNmax", &seedMultimapNmax)); parArray.push_back(new ParameterInfoScalar (-1, -1, "seedSplitMin", &seedSplitMin)); - + parArray.push_back(new ParameterInfoScalar (-1, -1, "seedMapMin", &seedMapMin)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "alignIntronMin", &alignIntronMin)); parArray.push_back(new ParameterInfoScalar (-1, -1, "alignIntronMax", &alignIntronMax)); parArray.push_back(new ParameterInfoScalar (-1, -1, "alignMatesGapMax", &alignMatesGapMax)); @@ -258,11 +274,27 @@ Parameters::Parameters() {//initalize parameters info parArray.push_back(new ParameterInfoScalar (-1, -1, "soloCBlen", &pSolo.cbL)); parArray.push_back(new ParameterInfoScalar (-1, -1, "soloUMIlen", &pSolo.umiL)); parArray.push_back(new ParameterInfoScalar (-1, -1, "soloBarcodeReadLength", &pSolo.bL)); - parArray.push_back(new ParameterInfoScalar (-1, -1, "soloCBwhitelist", &pSolo.soloCBwhitelist)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloBarcodeMate", &pSolo.barcodeReadIn)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloCBwhitelist", &pSolo.soloCBwhitelist)); parArray.push_back(new ParameterInfoScalar (-1, -1, "soloStrand", &pSolo.strandStr)); - parArray.push_back(new ParameterInfoVector (-1, -1, "soloOutFileNames", &pSolo.outFileNames)); - parArray.push_back(new ParameterInfoVector (-1, -1, "soloFeatures", &pSolo.featureIn)); - parArray.push_back(new ParameterInfoVector (-1, -1, "soloUMIdedup", &pSolo.umiDedup)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloOutFileNames", &pSolo.outFileNames)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloFeatures", &pSolo.featureIn)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloUMIdedup", &pSolo.umiDedup.typesIn)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloAdapterSequence",&pSolo.adapterSeq)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloAdapterMismatchesNmax", &pSolo.adapterMismatchesNmax)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloCBmatchWLtype", &pSolo.CBmatchWL.type)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloCBposition",&pSolo.cbPositionStr)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloUMIposition",&pSolo.umiPositionStr)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloCellFilter",&pSolo.cellFilter.type)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloUMIfiltering",&pSolo.umiFiltering.type)); + + parArray.push_back(new ParameterInfoVector (-1, -1, "soloMultiMappers", &pSolo.multiMap.typesIn)); + + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloClusterCBfile",&pSolo.clusterCBfile)); + parArray.push_back(new ParameterInfoScalar (-1, -1, "soloOutFormatFeaturesGeneField3",&pSolo.outFormat.featuresGeneField3)); + + parArray.push_back(new ParameterInfoVector (-1, -1, "soloInputSAMattrBarcodeSeq",&pSolo.samAtrrBarcodeSeq)); + parArray.push_back(new ParameterInfoVector (-1, -1, "soloInputSAMattrBarcodeQual",&pSolo.samAtrrBarcodeQual)); parameterInputName.push_back("Default"); parameterInputName.push_back("Command-Line-Initial"); @@ -273,6 +305,9 @@ Parameters::Parameters() {//initalize parameters info void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters: default, from files, from command line + + //hard-coded parameters + runRestart.type=0; ///////// Default parameters @@ -312,8 +347,7 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters val ='\"' + val + '\"'; }; commandLineFile += '\n' + key + ' ' + val; - } - else if (oneArg.substr(0,2)=="--") {//parameter name, cut -- + } else if (oneArg.substr(0,2)=="--") {//parameter name, cut -- commandLineFile +='\n' + oneArg.substr(2); } else {//parameter value if (oneArg.find_first_of(" \t")!=std::string::npos) {//there is white space in the argument, put "" around @@ -327,21 +361,20 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters scanAllLines(parStreamCommandLine, 1, 2); //read only initial Command Line parameters }; -// need to be careful since runMode and pGe.gDir are not Command-Line-Initial -// if (runMode=="genomeGenerate" && outFileNamePrefix=="./") {// for genome generation, output into pGe.gDir -// outFileNamePrefix=pGe.gDir; -// }; + createDirectory(outFileNamePrefix, S_IRWXU, "--outFileNamePrefix", *this); //TODO: runDirPerm is hard-coded now. Need to load it from command-line - inOut->logMain.open((outFileNamePrefix + "Log.out").c_str()); + outLogFileName=outFileNamePrefix + "Log.out"; + inOut->logMain.open(outLogFileName.c_str()); if (inOut->logMain.fail()) { ostringstream errOut; errOut <<"EXITING because of FATAL ERROR: could not create output file: "<logMain, EXIT_CODE_PARAMETER, *this); }; inOut->logMain << "STAR version=" << STAR_VERSION << "\n"; inOut->logMain << "STAR compilation time,server,dir=" << COMPILATION_TIME_PLACE << "\n"; + inOut->logMain << "STAR git: " << GIT_BRANCH_COMMIT_DIFF << "\n"; #ifdef COMPILE_FOR_LONG_READS inOut->logMain << "Compiled for LONG reads" << "\n"; #endif @@ -397,7 +430,7 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters ///////// Command Line Final - if (argInN>1) {//scan all parameters from command line and override previuos values + if (argInN>1) {//scan all parameters from command line and override previous values inOut->logMain << "###### All USER parameters from Command Line:\n" <logMain << "----------------------------------------\n\n" << flush; ///////////////////////////////////////// Old variables //splitting - Qsplit=0; maxNsplit=10; - minLsplit=seedSplitMin; - minLmap=5; - ////////////////////////////////////////////////////// Calculate and check parameters iReadAll=0; + + pGe.initialize(this); - if (runDirPermIn=="User_RWX") - { + //directory permissions TODO: this needs to be done before outPrefixFileName is created + if (runDirPermIn=="User_RWX") { runDirPerm=S_IRWXU; - } else if (runDirPermIn=="All_RWX") - { + } else if (runDirPermIn=="All_RWX") { runDirPerm= S_IRWXU | S_IRWXG | S_IRWXO; - } else - { + } else { ostringstream errOut; errOut << "EXITING because of FATAL INPUT ERROR: unrecognized option in --runDirPerm=" << runDirPerm << "\n"; errOut << "SOLUTION: use one of the allowed values of --runDirPerm : 'User_RWX' or 'All_RWX' \n"; @@ -461,12 +489,13 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters if (outTmpDir=="-") { outFileTmp=outFileNamePrefix +"_STARtmp/"; - sysRemoveDir (outFileTmp); + if (runRestart.type!=1) + sysRemoveDir (outFileTmp); } else { outFileTmp=outTmpDir + "/"; }; - if (mkdir (outFileTmp.c_str(),runDirPerm)!=0) { + if (mkdir (outFileTmp.c_str(),runDirPerm)!=0 && runRestart.type!=1) { ostringstream errOut; errOut <<"EXITING because of fatal ERROR: could not make temporary directory: "<< outFileTmp<<"\n"; errOut <<"SOLUTION: (i) please check the path and writing permissions \n (ii) if you specified --outTmpDir, and this directory exists - please remove it before running STAR\n"<logMain, EXIT_CODE_PARAMETER, *this); }; + runMode=runModeIn[0]; if (runMode=="alignReads") { inOut->logProgress.open((outFileNamePrefix + "Log.progress.out").c_str()); } else if (runMode=="inputAlignmentsFromBAM") { @@ -704,42 +734,16 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters inOut->logMain <<"WARNING: specified limitGenomeGenerateRAM="<0) ++ii;//skip comma - outSAMattrRGlineSplit.push_back(outSAMattrRGline.at(ii)); //star new RG line with the first field which must be ID:xxx - if (outSAMattrRGlineSplit.back().substr(0,3)!="ID:") { - ostringstream errOut; - errOut <<"EXITING because of FATAL INPUT ERROR: the first word of a line from --outSAMattrRGline="<logMain, EXIT_CODE_PARAMETER, *this); - }; - outSAMattrRG.push_back(outSAMattrRGlineSplit.back().substr(3)); //this adds the ID field - } else {//keep adding fields to this RG line, until the next comma - outSAMattrRGlineSplit.back()+="\t" + outSAMattrRGline.at(ii); - }; - }; - }; - }; - outSAMfilter.KeepOnlyAddedReferences=false; outSAMfilter.KeepAllAddedReferences=false; outSAMfilter.yes=true; - if (outSAMfilter.mode.at(0)=="KeepOnlyAddedReferences") - { + if (outSAMfilter.mode.at(0)=="KeepOnlyAddedReferences") { outSAMfilter.KeepOnlyAddedReferences=true; - } else if (outSAMfilter.mode.at(0)=="KeepAllAddedReferences") - { + } else if (outSAMfilter.mode.at(0)=="KeepAllAddedReferences") { outSAMfilter.KeepAllAddedReferences=true; - } else if (outSAMfilter.mode.at(0)=="None") - { + } else if (outSAMfilter.mode.at(0)=="None") { outSAMfilter.yes=false; - } else - { + } else { ostringstream errOut; errOut <<"EXITING because of FATAL INPUT ERROR: unknown/unimplemented value for --outSAMfilter: "<logMain, EXIT_CODE_PARAMETER, *this); - }; - - if (readFilesTypeN==1) { - readNmates=readFilesIn.size(); //for now the number of mates is defined by the number of input files - } else if (readFilesTypeN==10) {//find the number of mates from the SAM file - if (readFilesType.size()==2 && readFilesType.at(1)=="SE") { - readNmates=1; - } else if (readFilesType.size()==2 && readFilesType.at(1)=="PE") { - readNmates=2; - } else { - ostringstream errOut; - errOut <<"EXITING because of FATAL INPUT ERROR: --readFilesType SAM requires specifying SE or PE reads"<<"\n"; - errOut <<"SOLUTION: specify --readFilesType SAM SE for single-end reads or --readFilesType SAM PE for paired-end reads\n"; - exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); - }; - }; - readNmatesIn=readNmates; + readFilesInit(); //two-pass - if (parArray.at(twoPass.pass1readsN_par)->inputLevel>0 && twoPass.mode=="None") - { + if (parArray.at(twoPass.pass1readsN_par)->inputLevel>0 && twoPass.mode=="None") { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: --twopass1readsN is defined, but --twoPassMode is not defined\n"; errOut << "SOLUTION: to activate the 2-pass mode, use --twopassMode Basic"; @@ -808,24 +783,21 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters twoPass.yes=false; twoPass.pass2=false; if (twoPass.mode!="None") {//2-pass parameters - if (runMode!="alignReads") - { + if (runMode!="alignReads") { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: 2-pass mapping option can only be used with --runMode alignReads\n"; errOut << "SOLUTION: remove --twopassMode option"; exitWithError(errOut.str(),std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); }; - if (twoPass.mode!="Basic") - { + if (twoPass.mode!="Basic") { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: unrecognized value of --twopassMode="<logMain, EXIT_CODE_PARAMETER, *this); }; - if (twoPass.pass1readsN==0) - { + if (twoPass.pass1readsN==0) { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: --twopass1readsN = 0 in the 2-pass mode\n"; errOut << "SOLUTION: for the 2-pass mode, specify --twopass1readsN > 0. Use a very large number or -1 to map all reads in the 1st pass.\n"; @@ -853,44 +825,20 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters if (runMode=="alignReads" && pGe.gLoad!="Remove" && pGe.gLoad!="LoadAndExit") {//open reads files to check if they are present openReadsFiles(); - //check sizes of the mate files, if not the same, assume mates are not the same length - if (readNmates==1) { - readMatesEqualLengths=true; - } else if (readNmates > 2){ + if (readNends > 2 && pSolo.typeStr=="None") {//could have >2 mates only for Solo ostringstream errOut; - errOut <<"EXITING: because of fatal input ERROR: number of read mates files > 2: " < 2: " <logMain, EXIT_CODE_PARAMETER, *this); - } else if (readMatesLengthsIn=="Equal") { - readMatesEqualLengths=true; - } else if (readMatesLengthsIn=="NotEqual") { - readMatesEqualLengths=false; - } else { - ostringstream errOut; - errOut <<"EXITING because of FATAL input ERROR: the value of the parameter readMatesLengthsIn=" << readMatesLengthsIn <<" is not among the allowed values: Equal or NotEqual\n"; - errOut <<"SOLUTION: specify one of the allowed values: Equal or NotEqual\n"; - exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); }; if ( runMode=="alignReads" && outReadsUnmapped=="Fastx" ) {//open unmapped reads file - for (uint imate=0;imateoutUnmappedReadsStream[imate].open(ff.str().c_str()); }; }; - - - if (outFilterType=="Normal") { - outFilterBySJoutStage=0; - } else if (outFilterType=="BySJout") { - outFilterBySJoutStage=1; - } else { - ostringstream errOut; - errOut <<"EXITING because of FATAL input ERROR: unknown value of parameter outFilterType: " << outFilterType <<"\n"; - errOut <<"SOLUTION: specify one of the allowed values: Normal | BySJout\n"; - exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); - }; }; if (outSAMmapqUnique<0 || outSAMmapqUnique>255) { @@ -899,43 +847,10 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters errOut <<"SOLUTION: specify outSAMmapqUnique within the range of 0 to 255\n"; exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); }; - - // in/out buffers - #define BUFFER_InSizeFraction 0.5 - if (limitIObufferSizelogMain, EXIT_CODE_PARAMETER, *this); - }; - chunkInSizeBytesArray=(uint) int((limitIObufferSize-limitOutSJcollapsed*Junction::dataSize)*BUFFER_InSizeFraction)/2; - chunkOutBAMsizeBytes= (uint) int((1.0/BUFFER_InSizeFraction-1.0)*chunkInSizeBytesArray*2.0); - chunkInSizeBytes=chunkInSizeBytesArray-2*(DEF_readSeqLengthMax+1)-2*DEF_readNameLengthMax;//to prevent overflow - - //basic trimming - if (clip5pNbases.size()==1 && readNmates==2) clip5pNbases.push_back(clip5pNbases[0]); - if (clip3pNbases.size()==1 && readNmates==2) clip3pNbases.push_back(clip3pNbases[0]); - if (clip3pAfterAdapterNbases.size()==1 && readNmates==2) clip3pAfterAdapterNbases.push_back(clip3pAfterAdapterNbases[0]); - - //adapter clipping - if (clip3pAdapterSeq.size()==1 && readNmates==2) clip3pAdapterSeq.push_back(clip3pAdapterSeq[0]); - if (clip3pAdapterMMp.size()==1 && readNmates==2) clip3pAdapterMMp.push_back(clip3pAdapterMMp[0]); - for (uint imate=0;imatefastaOutSeqs.open("Seqs.out.fasta"); - }; - }; - + //variation var.yes=false; - if (var.vcfFile!="-") - { + if (var.vcfFile!="-") { var.yes=true; }; @@ -967,10 +882,9 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters errOut <<"SOLUTION: re-run STAR with --waspOutputMode ... and --outSAMtype BAM ... \n"; exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); }; - + //quantification parameters quant.yes=false; - quant.geneFull.yes=false; quant.geCount.yes=false; quant.trSAM.yes=false; quant.trSAM.bamYes=false; @@ -1014,6 +928,10 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters }; }; }; + //these may be set in STARsolo or in SAM attributes + quant.geneFull.yes=false; + quant.gene.yes=false; + outSAMstrandField.type=0; //none if (outSAMstrandField.in=="None") { @@ -1027,252 +945,63 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters exitWithError(errOut.str(),std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); }; + //SAM attributes + samAttributes(); + //solo pSolo.initialize(this); - - //outSAMattributes - outSAMattrPresent.NH=false;//TODO re-write as class with constructor? - outSAMattrPresent.HI=false; - outSAMattrPresent.AS=false; - outSAMattrPresent.NM=false; - outSAMattrPresent.MD=false; - outSAMattrPresent.nM=false; - outSAMattrPresent.jM=false; - outSAMattrPresent.jI=false; - outSAMattrPresent.RG=false; - outSAMattrPresent.MC=false; - outSAMattrPresent.XS=false; - outSAMattrPresent.vA=false; - outSAMattrPresent.vG=false; - outSAMattrPresent.vW=false; - outSAMattrPresent.ch=false; - outSAMattrPresent.rB=false; - outSAMattrPresent.CR=false; - outSAMattrPresent.CY=false; - outSAMattrPresent.UR=false; - outSAMattrPresent.UY=false; - - - //for quant SAM output only NH and HI flags - outSAMattrPresentQuant=outSAMattrPresent; - outSAMattrPresentQuant.NH=true; - outSAMattrPresentQuant.HI=true; - outSAMattrOrderQuant.push_back(ATTR_NH); - outSAMattrOrderQuant.push_back(ATTR_HI); - - vector vAttr1; - if (outSAMattributes.at(0)=="None") { - } else if (outSAMattributes.at(0)=="All"){ - vAttr1={"NH","HI","AS","nM","NM","MD","jM","jI","MC","ch"}; - } else if (outSAMattributes.at(0)=="Standard"){ - vAttr1={"NH","HI","AS","nM"}; - } else { - vAttr1=outSAMattributes; - }; - - for (uint ii=0;iilogMain << "WARNING --outSAMattributes contains XS, therefore STAR will use --outSAMstrandField intronMotif" <logMain, EXIT_CODE_PARAMETER, *this); - }; - }; - - if (!var.yes && (outSAMattrPresent.vA | outSAMattrPresent.vG)) { - ostringstream errOut; - errOut <<"EXITING because of fatal PARAMETER error: --outSAMattributes contains vA and/or vG tag(s), but --varVCFfile is not set\n"; - errOut <<"SOLUTION: re-run STAR with a --varVCFfile option, or without vA/vG tags in --outSAMattributes\n"; - exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); - }; - - if (!wasp.yes && outSAMattrPresent.vW) { - ostringstream errOut; - errOut <<"EXITING because of fatal PARAMETER error: --outSAMattributes contains vW tag, but --waspOutputMode is not set\n"; - errOut <<"SOLUTION: re-run STAR with a --waspOutputMode option, or without vW tags in --outSAMattributes\n"; - exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); - }; - - if (outSAMattrRG.size()>0 && !outSAMattrPresent.RG) { - outSAMattrOrder.push_back(ATTR_RG); - outSAMattrOrderQuant.push_back(ATTR_RG); - outSAMattrPresent.RG=true; - inOut->logMain << "WARNING --outSAMattrRG defines a read group, therefore STAR will output RG attribute" <logMain, EXIT_CODE_PARAMETER, *this); - }; - - if (outSAMstrandField.type==1 && !outSAMattrPresent.XS) { - outSAMattrOrder.push_back(ATTR_XS); - inOut->logMain << "WARNING --outSAMstrandField=intronMotif, therefore STAR will output XS attribute" <logMain << "WARNING --waspOutputMode is set, therefore STAR will output vW attribute" <logMain, EXIT_CODE_PARAMETER, *this); - }; - //initialize chimeric parameters - pCh.initialize(this); + //clipping + pClip.initialize(this); + //alignEnds alignEndsType.ext[0][0]=false; alignEndsType.ext[0][1]=false; alignEndsType.ext[1][0]=false; alignEndsType.ext[1][1]=false; - if (alignEndsType.in=="EndToEnd") - { + if (alignEndsType.in=="EndToEnd") { alignEndsType.ext[0][0]=true; alignEndsType.ext[0][1]=true; alignEndsType.ext[1][0]=true; alignEndsType.ext[1][1]=true; - } else if (alignEndsType.in=="Extend5pOfRead1" ) - { + } else if (alignEndsType.in=="Extend5pOfRead1" ) { alignEndsType.ext[0][0]=true; - } else if (alignEndsType.in=="Extend5pOfReads12" ) - { + } else if (alignEndsType.in=="Extend5pOfReads12" ) { alignEndsType.ext[0][0]=true; alignEndsType.ext[1][0]=true; - } else if (alignEndsType.in=="Extend3pOfRead1" ) - { + } else if (alignEndsType.in=="Extend3pOfRead1" ) { alignEndsType.ext[0][1]=true; - } else if (alignEndsType.in=="Local") - { + } else if (alignEndsType.in=="Local") { //nothing to do for now - } else - { + } else { ostringstream errOut; errOut <<"EXITING because of FATAL INPUT ERROR: unknown/unimplemented value for --alignEndsType: "<logMain, EXIT_CODE_PARAMETER, *this); }; -// #ifdef COMPILE_NO_SHM -// if (pGe.gLoad!="NoSharedMemory") { -// ostringstream errOut; -// errOut <<"EXITING because of FATAL INPUT ERROR: The code was compiled with NO SHARED MEMORY support, but pGe.gLoad="<logMain, EXIT_CODE_PARAMETER, *this); -// }; -// #endif - //open compilation-dependent streams #ifdef OUTPUT_localChains inOut->outLocalChains.open((outFileNamePrefix + "LocalChains.out.tab").c_str()); #endif -// genomeNumToNT={'A','C','G','T','N'}; strcpy(genomeNumToNT,"ACGTN"); - if (pGe.gLoad!="LoadAndKeep" && pGe.gLoad!="LoadAndRemove" && pGe.gLoad!="Remove" && pGe.gLoad!="LoadAndExit" && pGe.gLoad!="NoSharedMemory") {// find shared memory fragment - ostringstream errOut; - errOut << "EXITING because of FATAL INPUT ERROR: --genomeLoad=" << pGe.gLoad << "\n" <logMain, EXIT_CODE_PARAMETER, *this); - }; - //sjdb insert on the fly - sjdbInsert.pass1=false; sjdbInsert.pass2=false; sjdbInsert.yes=false; - if (pGe.sjdbFileChrStartEnd.at(0)!="-" || pGe.sjdbGTFfile!="-") - {//will insert annotated sjdb on the fly + if (pGe.sjdbFileChrStartEnd.at(0)!="-" || pGe.sjdbGTFfile!="-") {//will insert annotated sjdb on the fly sjdbInsert.pass1=true; sjdbInsert.yes=true; }; - if (twoPass.yes) - { + if (twoPass.yes) { sjdbInsert.pass2=true; sjdbInsert.yes=true; }; - if (pGe.gLoad!="NoSharedMemory" && sjdbInsert.yes ) - { + if (pGe.gLoad!="NoSharedMemory" && sjdbInsert.yes ) { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: on the fly junction insertion and 2-pass mappng cannot be used with shared memory genome \n" ; errOut << "SOLUTION: run STAR with --genomeLoad NoSharedMemory to avoid using shared memory\n" <logMain<<"WARNING: --limitBAMsortRAM=0, will use genome size as RAM limit for BAM sorting\n"; }; - for (uint ii=0; ii0) {//allow ends protrusion if (alignEndsProtrude.in.at(1)=="ConcordantPair") { alignEndsProtrude.concordantPair=true; @@ -1378,7 +1099,6 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters exitWithError(errOut.str(),std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); }; - //peOverlap if (peOverlap.NbasesMin>0) { peOverlap.yes=true; @@ -1393,7 +1113,7 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters alignSoftClipAtReferenceEnds.yes=false; } else { ostringstream errOut; - errOut << "EXITING because of fatal PARAMETERS error: unrecognized option in of --alignSoftClipAtReferenceEnds="<logMain, EXIT_CODE_PARAMETER, *this); }; @@ -1403,12 +1123,68 @@ void Parameters::inputParameters (int argInN, char* argIn[]) {//input parameters outSAMreadIDnumber=true; }; + + ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// these parameters do not depend on other parameters + ///////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////// limitIObufferSize + /* old before 2.7.9 + // in/out buffers + #define BUFFER_InSizeFraction 0.5 + if (limitIObufferSizelogMain, EXIT_CODE_PARAMETER, *this); + }; + chunkInSizeBytesArray=(uint) int((limitIObufferSize-limitOutSJcollapsed*Junction::dataSize)*BUFFER_InSizeFraction)/2; + chunkOutBAMsizeBytes= (uint) int((1.0/BUFFER_InSizeFraction-1.0)*chunkInSizeBytesArray*2.0); + chunkInSizeBytes=chunkInSizeBytesArray-2*(DEF_readSeqLengthMax+1)-2*DEF_readNameLengthMax;//to prevent overflow + */ + + if (limitIObufferSize.size() != 2) + exitWithError("EXITING because of FATAL input ERROR: --limitIObufferSize requires 2 numbers since 2.7.9a.\n" + "SOLUTION: specify 2 numbers in --limitIObufferSize : size of input and output buffers in bytes.\n" + , std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + + chunkInSizeBytesArray = limitIObufferSize[0]/readNends; //array size + chunkInSizeBytes = chunkInSizeBytesArray-2*(DEF_readSeqLengthMax+1)-2*DEF_readNameLengthMax; //to prevent overflow - array is bigger to allow loading one read + chunkOutBAMsizeBytes = limitIObufferSize[1]; + + + ///////////////////////////////////////////////////////// outSJ + if (outSJ.type[0] == "None") { + outSJ.yes = false; + } else if (outSJ.type[0] == "Standard") { + outSJ.yes = true; + } else { + exitWithError("EXITING because of FATAL input ERROR: unrecognized option in --outSJtype " + outSJ.type[0] + '\n' + + "SOLUTION: use one of the allowed options: --outSJtype Standard OR None\n" + , std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + + if (outFilterType=="Normal") { + outFilterBySJoutStage=0; + } else if (outFilterType=="BySJout") { + if (!outSJ.yes) + exitWithError("EXITING because of FATAL input ERROR: --outFilterType BySJout requires --outSJtype Standard\n" + "SOLUTION: --outFilterType Normal OR --outFilterType BySJout --outSJtype Standard\n" + , std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + + outFilterBySJoutStage=1; + } else { + ostringstream errOut; + errOut <<"EXITING because of FATAL input ERROR: unknown value of parameter outFilterType: " << outFilterType <<"\n"; + errOut <<"SOLUTION: specify one of the allowed values: Normal | BySJout\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + //////////////////////////////////////////////// inOut->logMain << "Finished loading and checking parameters\n" < #include "ParametersChimeric.h" #include "ParametersSolo.h" +#include "ParametersClip.h" #include "ParametersGenome.h" #include #include +#include class Parameters { @@ -30,11 +32,16 @@ class Parameters { // run parameters string runMode; + vector runModeIn; int runThreadN; mode_t runDirPerm; string runDirPermIn; //permission for directores created at run-time int runRNGseed; //random number generator seed + struct { + int32 type;//0 no restart, 1 no mapping - restart from _STARtmp files + } runRestart; //restart options - in development + //parameters vector parametersFiles; @@ -43,7 +50,7 @@ class Parameters { //genome char genomeNumToNT[6]; - ParametersGenome pGe; + ParametersGenome pGe, pGeOut; //binning,windows,anchors uint winBinChrNbits, winBinNbits, winAnchorDistNbins, winFlankNbins, winBinN; @@ -54,30 +61,37 @@ class Parameters { //read parameters vector readFilesType; int readFilesTypeN; - string readFilesPrefix; + string readFilesPrefix, readFilesPrefixFinal; vector readFilesIn, readFilesInTmp; uint32 readFilesN; vector > readFilesNames; vector readFilesCommand; + vector readFilesManifest; + + string readFilesCommandString; //actual command string int readFilesIndex; pid_t readFilesCommandPID[MAX_N_MATES]; uint readMapNumber; uint iReadAll; - uint readNmates, readNmatesIn; + uint readNmates, readNends; string readMatesLengthsIn; + uint32 readQualityScoreBase; vector readNameSeparator; vector readNameSeparatorChar; string outSAMreadID; bool outSAMreadIDnumber; + + //new: structure for readFiles parameters + struct { + vector samAttrKeepIn; //input vector of SAM tags to keep, if readFilesType=SAMtag + std::unordered_set samAttrKeep; + bool samAttrKeepAll, samAttrKeepNone; + } readFiles; - vector clip5pNbases, clip3pNbases, clip3pAfterAdapterNbases; - vector clip3pAdapterMMp; - vector clip3pAdapterSeq; - char *clip3pAdapterSeqNum[MAX_N_MATES];//adapter sequence - numerical - bool readMatesEqualLengths; //whether or not the read mates have the same length, true if onyl one mate + ParametersClip pClip; //align parameters uint alignSJoverhangMin,alignSJDBoverhangMin,alignSplicedMateMapLmin; //min SJ donor/acceptor length @@ -125,7 +139,7 @@ class Parameters { uint seedNoneLociPerWindow; //max number of aligns from one piece per window uint seedSearchStartLmax; double seedSearchStartLmaxOverLread; //length of split start points - uint seedSplitMin; + uint64 seedSplitMin, seedMapMin; //chunk parameters uint chunkInSizeBytes,chunkInSizeBytesArray,chunkOutBAMsizeBytes; @@ -133,6 +147,7 @@ class Parameters { //output string outFileNamePrefix, outStd; string outTmpDir, outTmpKeep; + string outLogFileName; //SAM output string outBAMfileCoordName, outBAMfileUnsortedName, outQuantBAMfileName; @@ -151,7 +166,7 @@ class Parameters { int outSAMtlen; - struct {bool NH,HI,AS,NM,MD,nM,jM,jI,RG,XS,rB,vG,vA,vW,ch,MC,CR,CY,UR,UY;} outSAMattrPresent, outSAMattrPresentQuant; + struct {bool NH,HI,AS,NM,MD,nM,jM,jI,RG,XS,rB,vG,vA,vW,ha,ch,MC,CR,CY,UR,UY,CB,UB,GX,GN,gx,gn,sM,sS,sQ,cN;} outSAMattrPresent, outSAMattrPresentQuant; vector outSAMattrOrder, outSAMattrOrderQuant; int outBAMcompression; @@ -214,6 +229,11 @@ class Parameters { string outFilterType; //type of filtering int outFilterBySJoutStage; //indicates the stage of filtering by SJout + struct { + vector type; + bool yes; + } outSJ; + //output filtering SJs string outSJfilterReads; vector outSJfilterCountUniqueMin, outSJfilterCountTotalMin; @@ -254,13 +274,13 @@ class Parameters { } sjdbInsert; //storage limits - uint limitGenomeGenerateRAM; - uint limitIObufferSize; //max size of the in/out buffer, bytes - uint limitOutSAMoneReadBytes; - uint limitOutSJoneRead, limitOutSJcollapsed; - uint limitBAMsortRAM; - uint limitSjdbInsertNsj; - uint limitNreadsSoft; + uint64 limitGenomeGenerateRAM; + vector limitIObufferSize; //max size of the in/out buffer, bytes + uint64 limitOutSAMoneReadBytes; + uint64 limitOutSJoneRead, limitOutSJcollapsed; + uint64 limitBAMsortRAM; + uint64 limitSjdbInsertNsj; + uint64 limitNreadsSoft; // penalties intScore scoreGap, scoreGapNoncan, scoreGapGCAG, scoreGapATAC, scoreDelBase, scoreDelOpen, scoreInsBase, scoreInsOpen; @@ -274,25 +294,37 @@ class Parameters { bool yes; //if any quantification is done vector mode; //quantification mode input string - struct { - bool yes; - bool bamYes; - bool indel; - bool softClip; - bool singleEnd; - int bamCompression; - string ban; - } trSAM; - - struct { - bool yes; - string outFile; - } geCount; - - struct { - bool yes; - } geneFull; - + struct { + bool yes; + bool bamYes; + bool indel; + bool softClip; + bool singleEnd; + int bamCompression; + string ban; + } trSAM; + + struct { + bool yes; + string outFile; + } geCount; + + struct { + bool yes; + } geneFull; + + struct { + bool yes; + } geneFull_Ex50pAS; + + struct { + bool yes; + } geneFull_ExonOverIntron; + + struct { + bool yes; + } gene; + } quant; //variation parameters @@ -314,8 +346,7 @@ class Parameters { ParametersChimeric pCh; //splitting - char Qsplit; - uint maxNsplit, minLsplit, minLmap; + uint maxNsplit; //not really parameters, but global variables: array,2> sjAll; @@ -333,8 +364,10 @@ class Parameters { void scanAllLines (istream &streamIn, int inputLevel, int inputLevelRequested); void inputParameters (int argInN, char* argIn[]); //input parameters: default, from files, from command line void openReadsFiles(); + void readFilesInit(); void closeReadsFiles(); void readSAMheader(const string readFilesCommandString, const vector readFilesNames); - + void samAttributes(); + void samAttrRequiresBAM(bool attrYes, string attrTag); }; #endif // Parameters.h diff --git a/source/ParametersChimeric_initialize.cpp b/source/ParametersChimeric_initialize.cpp old mode 100644 new mode 100755 index 7fff3ee5..5c17008d --- a/source/ParametersChimeric_initialize.cpp +++ b/source/ParametersChimeric_initialize.cpp @@ -5,22 +5,19 @@ void ParametersChimeric::initialize(Parameters *pPin) { + out.bam=false; + out.junctions=false; + out.samOld=false; + out.bamHardClip=true;//default + if (segmentMin==0) return; pP=pPin; - - if (out.samOld) { - pP->inOut->outChimSAM.open((pP->outFileNamePrefix + "Chimeric.out.sam").c_str()); - pP->inOut->outChimSAM << pP->samHeader; - }; + pthread_mutex_init(&g_threadChunks.mutexOutChimSAM, NULL); pthread_mutex_init(&g_threadChunks.mutexOutChimJunction, NULL); - - out.bam=false; - out.junctions=false; - out.samOld=false; - out.bamHardClip=true;//default + for (const auto& type1 : out.type) { if (type1=="WithinBAM") { out.bam=true; @@ -39,7 +36,12 @@ void ParametersChimeric::initialize(Parameters *pPin) exitWithError(errOut.str(), std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; }; - + + if (out.samOld) { + pP->inOut->outChimSAM.open((pP->outFileNamePrefix + "Chimeric.out.sam").c_str()); + pP->inOut->outChimSAM << pP->samHeader; + }; + if (out.junctions) { pP->inOut->outChimJunction.open((pP->outFileNamePrefix + "Chimeric.out.junction").c_str()); @@ -78,10 +80,10 @@ void ParametersChimeric::initialize(Parameters *pPin) exitWithError(errOut.str(), std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; - if (multimapNmax>0 && (out.bam || out.samOld)) { + if (multimapNmax>0 && out.samOld) { ostringstream errOut; - errOut <<"EXITING because of fatal PARAMETERS error: --chimMultimapNmax > 0 (new chimeric detection) presently only works with --chimOutType Junctions\n"; - errOut <<"SOLUTION: re-run with --chimOutType Junctions\n"; + errOut <<"EXITING because of fatal PARAMETERS error: --chimMultimapNmax > 0 (new chimeric detection) presently only works with --chimOutType Junctions/WithinBAM\n"; + errOut <<"SOLUTION: re-run with --chimOutType Junctions/WithinBAM\n"; exitWithError(errOut.str(), std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; diff --git a/source/ParametersClip.h b/source/ParametersClip.h new file mode 100644 index 00000000..d7dfaa1b --- /dev/null +++ b/source/ParametersClip.h @@ -0,0 +1,37 @@ +#ifndef CODE_ParametersClip +#define CODE_ParametersClip + +#include "IncludeDefine.h" +#include "ClipMate.h" +#include "ClipCR4.h" +#include +#include + +class Parameters; + +class ReadClipInput +{ +public: + vector N; + vector NafterAd; + vector adSeq; + vector adMMp; +}; + +class ParametersClip +{// +public: + //bool yes; //trimming is performed + + vector adapterType; + + array in; + + void initialize(Parameters *pPin); + void initializeClipMates(vector> &clipMates); + +private: + Parameters *pP; +}; + +#endif diff --git a/source/ParametersClip_initialize.cpp b/source/ParametersClip_initialize.cpp new file mode 100644 index 00000000..f80257d3 --- /dev/null +++ b/source/ParametersClip_initialize.cpp @@ -0,0 +1,99 @@ +#include "ParametersClip.h" +#include "Parameters.h" +#include "SequenceFuns.h" +#include "ErrorWarning.h" + +void ParametersClip::initialize(Parameters *pPin) +{ + pP = pPin; + //yes = false; + + if (adapterType[0]!="Hamming" && adapterType[0]!="CellRanger4") { + exitWithError("EXITING because of fatal PARAMETER error: --clipAdapterType = " + adapterType[0] + " is not a valid option\n" + + "SOLUTION: use valid --adapterType options: Hamming OR CellRanger4\n", std::cerr, pPin->inOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + + for (uint32 im=0; iminOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + }; + + if (adapterType[0]=="CellRanger4") { + + if (in[1].adSeq.size()>1 || in[1].adSeq[0]!="-") { + exitWithError("EXITING because of fatal PARAMETER error: --clipAdapterType CellRanger4 uses fixed sequences for 5' (TSO) and 3' (polyA) adapters." + "\nSOLUTION: Do not use --clip3pAdapter* or --clip5pAdapter* options.\n", std::cerr, pPin->inOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + + in[0].adSeq[0] = "AAGCAGTGGTATCAACGCAGAGTACATGGG"; + in[1].adSeq[0] = "A"; + }; + + for (int ip=0; ip<2; ip++) {//if no clipping, repeat for all mates + if (in[ip].adSeq[0]=="-") { + in[ip].adSeq.resize(pP->readNmates, "-"); + in[ip].adMMp.resize(pP->readNmates, 0); + }; + + if (in[ip].N[0]==0) + in[ip].N.resize(pP->readNmates, 0); + + if (in[ip].NafterAd[0]==0) + in[ip].NafterAd.resize(pP->readNmates, 0); + }; + + array p53={"5","3"}; + + for (int ip=0; ip<2; ip++) {//check that readNmates values are provided + if (in[ip].adSeq.size() != pP->readNmates) { + exitWithError("EXITING because of fatal PARAMETER error: --clip" +p53[ip]+ "pAdapterSeq has to contain " +to_string(pP->readNmates)+ " values to match the number of mates." + "\nSOLUTION: specify " +to_string(pP->readNmates)+ "values in --clip" +p53[ip]+ "pAdapterSeq , for no clipping use -" + , std::cerr, pPin->inOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + + if (in[ip].adMMp.size() != pP->readNmates) { + exitWithError("EXITING because of fatal PARAMETER error: --clip" +p53[ip]+ "pAdapterMMp has to contain " +to_string(pP->readNmates)+ " values to match the number of mates." + "\nSOLUTION: specify " +to_string(pP->readNmates)+ "values in --clip" +p53[ip]+ "pAdapterMMp" + , std::cerr, pPin->inOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + + if (in[ip].NafterAd.size() != pP->readNmates) { + exitWithError("EXITING because of fatal PARAMETER error: --clip" +p53[ip]+ "pAfterAdapterNbases has to contain " +to_string(pP->readNmates)+ " values to match the number of mates." + "\nSOLUTION: specify " +to_string(pP->readNmates)+ "values in --clip" +p53[ip]+ "pAfterAdapterNbases , for no clipping use 0" + , std::cerr, pPin->inOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + + if (in[ip].N.size() != pP->readNmates) { + exitWithError("EXITING because of fatal PARAMETER error: --clip" +p53[ip]+ "pNbases has to contain " +to_string(pP->readNmates)+ " values to match the number of mates." + "\nSOLUTION: specify " +to_string(pP->readNmates)+ "values in --clip" +p53[ip]+ "pNbases , for no clipping use 0" + , std::cerr, pPin->inOut->logMain, EXIT_CODE_PARAMETER, *pPin); + }; + }; +}; + +void ParametersClip::initializeClipMates(vector> &clipMates) +{ + clipMates.resize(pP->readNends); + + for (uint32 im=0; imreadNmates) {//true mates + clipMates[im][ip].initialize(in[ip].N[im], in[ip].adSeq[im], in[ip].NafterAd[im], in[ip].adMMp[im]); + } else {//barcode read, no clipping + //back() effectively duplicates the values for 2nd mate - if only one value was given in paramerter input + clipMates[im][ip].initialize(0, "-", 0, 0); + }; + }; + }; +}; diff --git a/source/ParametersGenome.cpp b/source/ParametersGenome.cpp new file mode 100644 index 00000000..8897ac26 --- /dev/null +++ b/source/ParametersGenome.cpp @@ -0,0 +1,57 @@ +#include "ParametersGenome.h" +#include "Parameters.h" +#include "ErrorWarning.h" + +void ParametersGenome::initialize(Parameters *pPin) +{ + pP=pPin; + + if (gDir.back()!='/') { + gDir += '/'; + }; + + //genome transformation + if (transform.typeString=="None") { + transform.type=0; + } else if (transform.typeString=="Haploid") { + transform.type=1; + } else if (transform.typeString=="Diploid") { + transform.type=2; + } else { + ostringstream errOut; + errOut << "EXITING because of FATAL PARAMETER ERROR: unrecognized option in --outTransformType = " << transform.typeString << "\n"; + errOut << "SOLUTION: use one of the allowed values for --outTransformType : 'None' or 'Haploid' or 'Diploid' \n"; + exitWithError(errOut.str(), std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + transform.outYes = transform.outSAM = transform.outSJ = false; + if (transform.output.at(0) == "None") { + //nothing to do + } else { + for (auto &ot: transform.output) { + if (ot == "SAM") { + transform.outYes = transform.outSAM = true; + } else if (ot == "SJ") { + transform.outYes = transform.outSJ = true; + } else { + exitWithError("EXITING because of FATAL PARAMETER ERROR: unrecognized option in --outTransformOutput = " + ot + '\n' + + "SOLUTION: use allowed values for --outTransformOutput: None or SAM and/or SJ\n" + ,std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + }; + }; + + if (gTypeString!="Full" && gTypeString!="Transcriptome" && gTypeString!="SuperTranscriptome") { + ostringstream errOut; + errOut << "EXITING because of FATAL parameter error: --genomeType=" << gTypeString << "\n"; + errOut << "SOLUTION: use one of the allowed values for --genomeLoad : Full OR Transcriptome OR SuperTranscriptome\n" <inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + if (gLoad!="LoadAndKeep" && gLoad!="LoadAndRemove" && gLoad!="Remove" && gLoad!="LoadAndExit" && gLoad!="NoSharedMemory") {// find shared memory fragment + ostringstream errOut; + errOut << "EXITING because of FATAL INPUT ERROR: --genomeLoad=" << gLoad << "\n" <inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; +}; \ No newline at end of file diff --git a/source/ParametersGenome.h b/source/ParametersGenome.h old mode 100644 new mode 100755 index 905e7e19..28b61728 --- a/source/ParametersGenome.h +++ b/source/ParametersGenome.h @@ -1,34 +1,56 @@ #ifndef CODE_ParametersGenome #define CODE_ParametersGenome +#include "IncludeDefine.h" + +class Parameters; + class ParametersGenome {//"constant" genome parameters - user input - public: - string gDir; - string gLoad; - vector gFastaFiles; - vector gChainFiles; - string gConsensusFile; +public: + string gDir; + string gLoad; + + uint32 gType;//type code + string gTypeString; + + vector gFastaFiles; + vector gChainFiles; + //string gConsensusFile; DEPRECATED + + struct { + int32 type; + string typeString; + string vcfFile; + vector output; //which output to transform + bool outYes, outSAM, outSJ; + } transform; + + uint gSAindexNbases;//length of the SA pre-index strings + uint gChrBinNbits; + uint gSAsparseD;//SA sparsity + uint gSuffixLengthMax;//maximum length of the suffixes, has to be longer than read length + vector gFileSizes;//size of the genome files - uint gSAindexNbases;//length of the SA pre-index strings - uint gChrBinNbits; - uint gSAsparseD;//SA sparsity - uint gSuffixLengthMax;//maximum length of the suffixes, has to be longer than read length - vector gFileSizes;//size of the genome files + vector sjdbFileChrStartEnd; + string sjdbGTFfile; + string sjdbGTFchrPrefix; + + string sjdbGTFfeatureExon; + string sjdbGTFtagExonParentTranscript; + string sjdbGTFtagExonParentGene; + vector sjdbGTFtagExonParentGeneName; + vector sjdbGTFtagExonParentGeneType; + + string sjdbInsertSave; + uint sjdbOverhang; + int sjdbOverhang_par; + int sjdbScore; + + void initialize(Parameters *Pin); - vector sjdbFileChrStartEnd; - string sjdbGTFfile; - string sjdbGTFchrPrefix; - - string sjdbGTFfeatureExon; - string sjdbGTFtagExonParentTranscript; - string sjdbGTFtagExonParentGene; - vector sjdbGTFtagExonParentGeneName; - vector sjdbGTFtagExonParentGeneType; - - string sjdbInsertSave; - uint sjdbOverhang; - int sjdbOverhang_par; - int sjdbScore; +private: + Parameters *pP; + }; -#endif \ No newline at end of file +#endif diff --git a/source/ParametersSolo.cpp b/source/ParametersSolo.cpp index 5f1c9e18..fab4cbb9 100755 --- a/source/ParametersSolo.cpp +++ b/source/ParametersSolo.cpp @@ -7,16 +7,45 @@ #include -const vector ParametersSolo::featureNames={"Gene","SJ","GeneFull"}; - void ParametersSolo::initialize(Parameters *pPin) { pP=pPin; - if (typeStr=="None") { - type=0; + cellFiltering(); + if (pP->runMode=="soloCellFiltering") {//only filtering happens, do not need any other parameters + yes=true; + umiDedup.typesIn = {"NoDedup"}; //this does not affect the results - the dedup had been done when raw matrix was generated + umiDedup.initialize(this); return; - } else if (typeStr=="Droplet") { + }; + + //constants - may turn into parameters in the future + redistrReadsNfiles = 3*pP->runThreadN; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////--soloType + barcodeStart=barcodeEnd=0; //this means that the entire barcodeRead is considered barcode. Will change it for simple barcodes. + yes = true; + if (typeStr=="None" || typeStr=="SmartSeq") {//solo SAM attributes not allowed + + if ( pP->outSAMattrPresent.CR || pP->outSAMattrPresent.CY || pP->outSAMattrPresent.UR + || pP->outSAMattrPresent.UY || pP->outSAMattrPresent.CB || pP->outSAMattrPresent.UB + || pP->outSAMattrPresent.sS || pP->outSAMattrPresent.sQ || pP->outSAMattrPresent.sM + ) { + ostringstream errOut; + errOut <<"EXITING because of FATAL INPUT ERROR: --outSAMattributes contains CR/CY/UR/UY/CB/UB tags which are not allowed for --soloType " << typeStr <<'\n'; + errOut <<"SOLUTION: re-run STAR without these attribures\n"; + exitWithError(errOut.str(), std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + }; + + if (typeStr=="None") { + type = SoloTypes::None; + yes = false; + samAttrYes = false; + return; + } else if (typeStr=="CB_UMI_Simple" || typeStr=="Droplet") { + type=SoloTypes::CB_UMI_Simple; if (umiL > 16) { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: UMI length is too long: --soloUMIlen="<inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; - type=1; + + cbumiL=cbL+umiL; if (bL==1) - bL=cbL+umiL; - pP->readNmates=1; //output mates TODO: check that readNmatesIn==2 + bL=cbumiL; + + barcodeStart=min(cbS,umiS)-1; + barcodeEnd=max(cbS+cbL,umiS+umiL)-2; + + } else if (typeStr=="CB_UMI_Complex") { + type=SoloTypes::CB_UMI_Complex; + bL=0;//no fixed length for barcode sequence + cbumiL=0; + + } else if (typeStr=="CB_samTagOut") { + type=SoloTypes::CB_samTagOut; + cbumiL=cbL+umiL; + if (bL==1) + bL=cbumiL; + + barcodeStart=min(cbS,umiS)-1; + barcodeEnd=max(cbS+cbL,umiS+umiL)-2; + + } else if (typeStr=="SmartSeq") { + type=SoloTypes::SmartSeq; + } else { ostringstream errOut; errOut << "EXITING because of fatal PARAMETERS error: unrecognized option in --soloType="<inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////input read files + barcodeRead=-1; + barcodeReadSeparate=false; + + if (pP->readFilesTypeN != 10) {//input from FASTQ + if (type==SoloTypes::SmartSeq) {//no barcode read + //TODO: a lot of parameters should not be defined for SmartSeq option - check it here + } else {//all other types require barcode read + if (barcodeReadIn == 0) {//barcode read is separate - needs to be the last read in --readFilesIn + if (pP->readNends < 2) { + exitWithError("EXITING because of fatal PARAMETERS error: --soloType (except SmartSeq) with --soloBarcodeMate 0 (default) require 2 reads or 3 reads, where the last read is the barcode read.\n" + "SOLUTION: if barcode is in a separate mate, specify it as the last file in --readFilesIn. If barcode sequence is a part of one of the mates, specify that mate with --soloBarcodeMate 1 (or 2 or 3)" + ,std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + pP->readNmates = pP->readNends-1; //true mates, excluding barcode read + barcodeRead = pP->readNends-1;//the barcode read is always the last one + } else if (barcodeReadIn > pP->readNends) { + exitWithError("EXITING because of fatal PARAMETERS error: --soloBarcodeMate " +to_string(barcodeReadIn)+ "is larger than number of mates " + to_string(pP->readNends) + + "\nSOLUTION: specify --soloBarcodeMate <= than the number of mates.",std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + } else {//barcode sequence is in one of the mates + if (type != SoloTypes::CB_UMI_Simple) { + exitWithError("EXITING because of fatal PARAMETERS error: --soloBarcodeMate " +to_string(barcodeReadIn)+ ">0 for is not allowed for --soloType " + typeStr + + "\nSOLUTION: specify --soloBarcodeMate 0 or --soloType CB_UMI_Simple",std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + barcodeRead = barcodeReadIn-1; + barcodeReadSeparate = true; + bL = 0; //>0 only for separate barcode read + + if ( pP->pClip.in[0].N[barcodeRead] == 0 && pP->pClip.in[1].N[barcodeRead] == 0 ){//clipping not specified for the mate with barcodes + exitWithError("EXITING because of fatal PARAMETERS error: --soloBarcodeMate " +to_string(barcodeReadIn)+ " specifies that barcode sequence is a part of the mate " +to_string(barcodeReadIn)+ + ", which requires clipping the barcode off this mate." + "\nSOLUTION: clip the barcode sequence from 5' or/and 3' with --clip5pNbases or/and --clip3pNbases . The values for mate1 and mate2 have to specified, specify 0 for no clipping.",std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + }; + }; + } else if (pP->readFilesTypeN == 10) {//input from SAM + if (typeStr=="SmartSeq") { + exitWithError("EXITING because of fatal PARAMETERS error: --readFilesType SAM SE/PE cannot be used with --soloType SmartSeq\n" + "SOLUTION: for Smart-seq input from BAM files, use --soloType CB_UMI_Simple , create whitelist of SmartSeq file names, and specify the SAM tag that records these file names in --soloInputSAMattrBarcodeSeq" + , std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + + if (samAtrrBarcodeSeq.at(0) == "-") { + exitWithError("EXITING because of fatal PARAMETERS error: --readFilesType SAM SE/PE requires --soloInputSAMattrBarcodeSeq.\n" + "SOLUTION: specify input SAM attributes for barcode sequence in --soloInputSAMattrBarcodeSeq, and (optionally) quality with --soloInputSAMattrBarcodeQual" + , std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + if (samAtrrBarcodeQual.at(0) == "-") { + warningMessage(" since --readFilesType SAM SE/PE --soloInputSAMattrBarcodeQual - : qualities for barcode read will be replaced with 'H'", pP->inOut->logMain,std::cerr, *pP); + samAtrrBarcodeQual.clear(); + }; + + for (auto &tag: samAtrrBarcodeSeq) { + if (tag.size()!=2) { + exitWithError("EXITING because of fatal PARAMETERS error: --soloInputSAMattrBarcodeSeq attributes have to be two-letter strings.\n" + "SOLUTION: specify correct two-letter strings in --soloInputSAMattrBarcodeSeq", + std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + tag.insert(0,1,'\t'); + }; + + for (auto &tag: samAtrrBarcodeQual) { + if (tag.size()!=2) { + exitWithError("EXITING because of fatal PARAMETERS error: --soloInputSAMattrBarcodeQual attributes have to be two-letter strings.\n" + "SOLUTION: specify correct two-letter strings in --soloInputSAMattrBarcodeQual", + std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + tag.insert(0,1,'\t'); + }; + }; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////// soloStrand if (strandStr=="Unstranded") { strand=-1; } else if (strandStr=="Forward") { @@ -53,51 +181,77 @@ void ParametersSolo::initialize(Parameters *pPin) exitWithError(errOut.str(),std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; - featureInd.resize(featureNames.size(),-1); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////// features + featureInd.fill(-1); + featureYes.fill(false); + featureFirst = -1; for (auto &fin : featureIn) { - bool finGood=false; - for (uint32 ii=0; iiinOut->logMain, EXIT_CODE_PARAMETER, *pP); - }; }; - nFeatures=features.size(); + std::sort(features.begin(), features.end()); + for (uint32 ii=0; iiinOut->logMain, EXIT_CODE_PARAMETER, *pP); - }; + if (nFeatures != featureIn.size()) { + ostringstream errOut; + errOut << "EXITING because of fatal PARAMETERS error: unrecognized option(s) in --soloFeatures "; + for (auto &fname : featureIn) + errOut << fname <<" "; + errOut << "\nSOLUTION: use allowed option: "; + errOut <inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; - ///////////// finished parameters input + if (featureYes[SoloFeatureTypes::Velocyto] && type==SoloTypes::SmartSeq) { + string errOut = "EXITING because of fatal PARAMETERS error: --soloFeatures Velocyto is presently not compatible with --soloType SmartSeq .\n"; + errOut += "SOLUTION: re-run without --soloFeatures Velocyto ."; + exitWithError(errOut, std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + if (featureYes[SoloFeatureTypes::Gene]) { + pP->quant.gene.yes = true; + pP->quant.yes = true; + }; + if (featureYes[SoloFeatureTypes::GeneFull]) { + pP->quant.geneFull.yes = true; + pP->quant.yes = true; + if (!featureYes[SoloFeatureTypes::Gene]) + pP->quant.gene.yes=false; //if GeneFull is requested, but Gene is not, turn it off - it could have been turned on because of GX/GN attributes + }; + if (featureYes[SoloFeatureTypes::GeneFull_Ex50pAS]) { + pP->quant.geneFull_Ex50pAS.yes = true; + pP->quant.yes = true; + if (!featureYes[SoloFeatureTypes::Gene]) + pP->quant.gene.yes=false; //if GeneFull is requested, but Gene is not, turn it off - it could have been turned on because of GX/GN attributes + }; + if (featureYes[SoloFeatureTypes::GeneFull_ExonOverIntron]) { + pP->quant.geneFull_ExonOverIntron.yes = true; + pP->quant.gene.yes = true; //needed to prioritize exons over introns + pP->quant.yes = true; + }; + + //initialize CB match to WL types + init_CBmatchWL(); + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////umiDedup + umiDedup.initialize(this); + + ///////////// finished parameters input + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //make output directory if needed if ( outFileNames[0].find_last_of("/") < outFileNames[0].size() ) {//need to create dir string dir1=pP->outFileNamePrefix+outFileNames[0].substr(0,outFileNames[0].find_last_of("/")); @@ -116,55 +270,410 @@ void ParametersSolo::initialize(Parameters *pPin) umiMaskLow=(uint32) ( (((uint64)1)<1) { ostringstream errOut; - errOut << "EXITING because of FATAL ERROR in INPUT parameters: --soloCBwhitelist is not defined\n"; - errOut << "SOLUTION: in --soloCBwhitelist specify path to and name of the whitelist file, or None for CB demultiplexing without whitelist \n"; + errOut << "EXITING because of FATAL ERROR in INPUT parameters: --soloCBwhitelist contains more than one file which is not allowed with --soloType CB_UMI_Simple \n"; + errOut << "SOLUTION: in --soloCBwhitelist specify only one whitelist file \n"; exitWithError(errOut.str(),std::cerr, pP->inOut->logMain, EXIT_CODE_INPUT_FILES, *pP); - } else if (soloCBwhitelist=="None") { - cbWLyes=false; - } else { - cbWLyes=true; - ifstream & cbWlStream = ifstrOpen(soloCBwhitelist, ERROR_OUT, "SOLUTION: check the path and permissions of the CB whitelist file: " + soloCBwhitelist, *pP); - string seq1; - while (cbWlStream >> seq1) { - if (seq1.size() != cbL) { + } else if (soloCBwhitelist[0]=="-") { ostringstream errOut; - errOut << "EXITING because of FATAL ERROR in input CB whitelist file: "<< soloCBwhitelist <<" the total length of barcode sequence is " << seq1.size() << " not equal to expected " <inOut->logMain, EXIT_CODE_INPUT_FILES, *pP); + } else if (soloCBwhitelist[0]=="None") { + cbWLyes=false; + } else { + cbWLyes=true; + ifstream & cbWlStream = ifstrOpen(soloCBwhitelist[0], ERROR_OUT, "SOLUTION: check the path and permissions of the CB whitelist file: " + soloCBwhitelist[0], *pP); + string seq1; + while (cbWlStream >> seq1) { + if (seq1.size() != cbL) { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR in input CB whitelist file: "<< soloCBwhitelist[0] <<" the total length of barcode sequence is " << seq1.size() << " not equal to expected " <inOut->logMain, EXIT_CODE_INPUT_FILES, *pP); + }; + uint64 cb1; + if (convertNuclStrToInt64(seq1,cb1)) {//convert to 2-bit format + cbWL.push_back(cb1); + } else { + pP->inOut->logMain << "WARNING: CB whitelist sequence contains non-ACGT base and is ignored: " << seq1 <inOut->logMain << "WARNING: CB whitelist sequence contains non-ACGT and is ignored: " << seq1 <inOut->logMain, EXIT_CODE_INPUT_FILES, *pP); + }; + }; + + std::sort(cbWL.begin(),cbWL.end());//sort + auto un1=std::unique(cbWL.begin(),cbWL.end());//collapse identical + cbWL.resize(std::distance(cbWL.begin(),un1)); + cbWLsize=cbWL.size(); + pP->inOut->logMain << "Number of CBs in the whitelist = " << cbWLsize <outSAMattrRG; + cbWLsize=cbWLstr.size(); + cbWLyes=true; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + } else if (type==SoloTypes::CB_UMI_Complex) {//complex barcodes: multiple whitelist (one for each CB), varying CB length + cbWLyes=true; //for complex barcodes, no-whitelist option is not allowed for now + + adapterYes=false; + if (adapterSeq!="-") + adapterYes=true; + + if (cbPositionStr.size() != soloCBwhitelist.size()) { + ostringstream errOut; + errOut << "EXITING because of fatal PARAMETER error: number of barcodes in --soloCBposition : "<< cbPositionStr.size() <<" is not equal to the number of WhiteLists in --soloCBwhitelist : " << soloCBwhitelist.size() <<"\n" ; + errOut << "SOLUTION: make sure that the number of CB whitelists and CB positions are the same\n"; + exitWithError(errOut.str(),std::cerr, pP->inOut->logMain, EXIT_CODE_INPUT_FILES, *pP); + }; + cbV.resize(cbPositionStr.size()); + for (uint32 ii=0; ii> seq1) {//cycle over one WL file + uint64 cb1; + if (!convertNuclStrToInt64(seq1,cb1)) {//convert to 2-bit format + pP->inOut->logMain << "WARNING: CB whitelist sequence contains non-ACGT base and is ignored: " << seq1 <=cbV[icb].wl.size()) + cbV[icb].wl.resize(len1+1);//add new possible lengths to this CB + cbV[icb].wl.at(len1).push_back(cb1); }; + + cbV[icb].sortWhiteList(this); + cbV[icb].wlFactor=cbWLsize; + cbWLsize *= cbV[icb].totalSize; }; + + complexWLstrings(); }; - std::sort(cbWL.begin(),cbWL.end()); - auto un1=std::unique(cbWL.begin(),cbWL.end()); - cbWL.resize(std::distance(cbWL.begin(),un1)); - //qsort(cbWL.data(),cbWL.size(),sizeof(uint64),funCompareNumbers); + time_t rawTime; + time(&rawTime); + pP->inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished reading, sorting and deduplicating CB whitelist sequences." <quant.trSAM.yes) { - pP->quant.yes = true; - pP->quant.trSAM.yes = true; - pP->quant.trSAM.bamYes = false; - pP->quant.trSAM.bamCompression = -2; - pP->quant.trSAM.indel = true; - pP->quant.trSAM.softClip = true; - pP->inOut->logMain << "Turning on Genomic->Transcriptomic coordinate conversion for STARsolo\n"; + //////////////////////////////////////////////////////////////SAM attributes + samAttrYes=false; + if ( (pP->outSAMattrPresent.CB || pP->outSAMattrPresent.UB) && type!=SoloTypes::CB_samTagOut) { + samAttrYes=true; + if (!pP->outBAMcoord) { + ostringstream errOut; + errOut << "EXITING because of fatal PARAMETERS error: CB and/or UB attributes in --outSAMattributes can only be output in the sorted BAM file.\n"; + errOut << "SOLUTION: re-run STAR with --outSAMtype BAM SortedByCoordinate ...\n"; + exitWithError(errOut.str(),std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + } else if ( pP->outSAMattrPresent.UB && type==SoloTypes::CB_samTagOut) { + exitWithError("EXITING because of fatal PARAMETERS error: UB attribute (corrected UMI) in --outSAMattributes cannot be used with --soloType CB_samTagOut \n" \ + "SOLUTION: instead, use UR (uncorrected UMI) in --outSAMattributes\n", std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + ////////////////////////////////////////////////////////////////readInfoYes: which feature is used to fill readInfo. Only one feature is allowed + readInfoYes.fill(false); + if (featureYes[SoloFeatureTypes::VelocytoSimple] || featureYes[SoloFeatureTypes::Velocyto]) {//turn readInfo on for Gene needed by VelocytoSimple + readInfoYes[SoloFeatureTypes::Gene]=true; + } else if (samAttrYes){//pSolo.samAttrFeature=0 by default, so need to check samAttrYes + if ( featureFirst == SoloFeatureTypes::Gene || featureFirst == SoloFeatureTypes::GeneFull || + featureFirst == SoloFeatureTypes::GeneFull_Ex50pAS || featureFirst == SoloFeatureTypes::GeneFull_ExonOverIntron ) { + samAttrFeature = featureFirst; + } else { + ostringstream errOut; + errOut << "EXITING because of fatal PARAMETERS error: CB and/or UB attributes in --outSAMattributes require --soloFeatures Gene OR/AND GeneFull OR/AND GeneFull_Ex50pAS.\n"; + errOut << "SOLUTION: re-run STAR adding Gene AND/OR GeneFull OR/AND GeneFull_Ex50pAS OR/AND GeneFull_ExonOverIntron to --soloFeatures\n"; + exitWithError(errOut.str(),std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + readInfoYes[samAttrFeature]=true; + }; + readIndexYes = readInfoYes; + + ///////////////////////////////////////////////////////////////////umi filtering + if (umiFiltering.type[0]=="MultiGeneUMI") { + umiFiltering.MultiGeneUMI = true; + umiFiltering.yes = true; + } else if (umiFiltering.type[0]=="MultiGeneUMI_All") { + umiFiltering.MultiGeneUMI_All = true; + umiFiltering.yes = true; + } else if (umiFiltering.type[0]=="MultiGeneUMI_CR") { + umiFiltering.MultiGeneUMI_CR = true; + if (umiDedup.typesIn.size()>1 || umiDedup.typesIn.at(0) != "1MM_CR") + exitWithError("EXITING because of fatal PARAMETERS error: --soloUMIfiltering MultiGeneUMI_CR only works with --soloUMIdedup 1MM_CR" + "\nSOLUTION: rerun with --soloUMIfiltering MultiGeneUMI_CR --soloUMIdedup 1MM_CR \n", + std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + } else if (umiFiltering.type[0]=="-") { + //nothing to do + } else { + exitWithError("EXITING because of fatal PARAMETERS error: unrecognized option in --soloUMIfiltering=" + umiFiltering.type[0] + + "\nSOLUTION: use allowed options: - or MultiGeneUMI or MultiGeneUMI_CR \n", + std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); }; - if (featureYes[2]) - pP->quant.geneFull.yes=true; - time_t rawTime; - time(&rawTime); - pP->inOut->logMain << timeMonthDayTime(rawTime) << "Finished reading CB whitelist sequences: " << cbWL.size() <inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + readIndexYes[SoloFeatureTypes::Gene]=true; + readIndexYes[SoloFeatureTypes::GeneFull]=true; + readIndexYes[SoloFeatureTypes::GeneFull_Ex50pAS]=true; + readIndexYes[SoloFeatureTypes::GeneFull_ExonOverIntron]=true; + }; +}; + +///////////////////////////////// +void ParametersSolo::umiSwapHalves(uint32 &umi) { + uint32 high=umi>>(umiL); + umi &= umiMaskLow; //remove high + umi <<= (umiL); //move low to high + umi |= high; //add high }; + +void ParametersSolo::complexWLstrings() { + + cbWLstr.resize(cbWLsize); + + for (auto &cb : cbV) {//initialize + cb.iCB=0; + cb.iLen=cb.minLen; + }; + + for (uint32 ii=0; iiinOut->logMain << "ParametersSolo: using hardcoded filtering parameters for --soloCellFilterType CellRanger2.2" <inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + pP->inOut->logMain << "ParametersSolo: --soloCellFilterType CellRanger2.2 filtering parameters: " << pars1 <> cellFilter.knee.nExpectedCells >> cellFilter.knee.maxPercentile >> cellFilter.knee.maxMinRatio; + + } else if (cellFilter.type[0]=="EmptyDrops_CR") { + if (cellFilter.type.size()==1) { + pP->inOut->logMain << "ParametersSolo: using hardcoded filtering parameters for --soloCellFilterType EmptyDrops_CR\n"; + pars1="3000 0.99 10 45000 90000 500 0.01 20000 0.01 10000"; + } else if (cellFilter.type.size()<11) { + string errOut="EXITING because of fatal PARAMETERS error: --soloCellFilterType EmptyDrops_CR requires exactly 10 numerical parameters"; + errOut += "\nSOLUTION: re-run with --soloCellFilterType EmptyDrops_CR "; + errOut += " \n"; + exitWithError(errOut, std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + pP->inOut->logMain << "ParametersSolo: --soloCellFilterType EmptyDrops_CR filtering parameters: " << pars1 <> cellFilter.knee.nExpectedCells >> cellFilter.knee.maxPercentile >> cellFilter.knee.maxMinRatio; + parsStream >> cellFilter.eDcr.indMin >> cellFilter.eDcr.indMax >> cellFilter.eDcr.umiMin >> cellFilter.eDcr.umiMinFracMedian; + parsStream >> cellFilter.eDcr.candMaxN >> cellFilter.eDcr.FDR >> cellFilter.eDcr.simN; + + } else if (cellFilter.type[0]=="TopCells") { + if (cellFilter.type.size()<2) { + string errOut="EXITING because of fatal PARAMETERS error: number of cells not specified for --soloCellFilterType TopCells"; + errOut += "\nSOLUTION: --soloCellFilterType TopCells \n"; + exitWithError(errOut, std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + cellFilter.topCells=stoi(cellFilter.type[1]); + } else if (cellFilter.type[0]=="None") { + //nothing to do + } else { + exitWithError("EXITING because of fatal PARAMETERS error: unrecognized option in --soloCellFilterType=" + cellFilter.type[0] + "\nSOLUTION: use allowed options: CellRanger2.2 or None\n", + std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; +}; + +void UMIdedup::initialize(ParametersSolo *pS) +{ + yes.N = 0; + countInd.I.fill((uint32_t) -1); //marks types not used + yes.B.fill(false); + + for (uint32_t iin=0; iinpP->inOut->logMain, EXIT_CODE_PARAMETER, *pS->pP); + }; + + types.push_back(itype); + yes.B[itype] = true; + yes.N++; + countInd.I[itype] = iin + 1; //for each type, which column itype's recorded in + + if (pS->type == pS->SoloTypes::SmartSeq && (yes.All || yes.Directional || yes.CR) ) + exitWithError("EXITING because of fatal PARAMETERS error: --soloUMIdedup = " + typesIn[iin] + " is not allowed for --soloType SmartSeq\n" + + "SOLUTION: use allowed options: Exact and/or NoDedup\n" + ,std::cerr, pS->pP->inOut->logMain, EXIT_CODE_PARAMETER, *pS->pP); + }; + + //hard-coded for now + typeMain = types[0]; //main is the 0th entry in typesIn + countInd.main = 1; //hard-coded - 1 column is always main +}; + +void MultiMappers::initialize(ParametersSolo* pS) +{ + yes.N = 0; + countInd.I.fill((uint32) -1); //marks types not used + yes.B.fill(false); + + for (uint32 iin=0; iinpP->inOut->logMain, EXIT_CODE_PARAMETER, *pS->pP); + }; + + if (itype == typeI::Unique) + continue; //Unique type does not have to be recorded TODO use it to perform filtering and stats + + + types.push_back(itype); + yes.B[itype] = true; + yes.N++; + }; + + if (yes.N==0) {//only Unique, no multimappers + yes.multi=false; + return; + }; + + uint32 ind1=1; //start + for (const auto &itype : types) { + countInd.I[itype] = ind1; + ind1 += pS->umiDedup.yes.N; + }; + + //hard-coded for now + typeMain = types[0]; //main is the 0th entry in typesIn + countInd.main = 1; //hard-coded - 1 column is always main + + yes.multi = yes.Uniform | yes.Rescue | yes.PropUnique | yes.EM; +}; + +//////////////////////////////////////////////////// +void ParametersSolo::init_CBmatchWL() +{//CBmatchWL + bool incomp1 = typeStr=="CB_UMI_Complex" && (CBmatchWL.type!="Exact" && CBmatchWL.type!="1MM" && CBmatchWL.type!="ParseBio_ED3"); + incomp1 = incomp1 || (typeStr=="CB_samTagOut" && (CBmatchWL.type!="Exact" && CBmatchWL.type!="1MM")); + incomp1 = incomp1 || (typeStr!="CB_UMI_Complex" && CBmatchWL.type=="ParseBio_ED3"); + + if ( incomp1 ) { + ostringstream errOut; + errOut << "EXITING because of fatal PARAMETERS error: --soloCBmatchWLtype "<< CBmatchWL.type << " does not work with --soloType " << typeStr << "\n"; + errOut << "SOLUTION: use allowed option: use --soloCBmatchWLtype Exact (exact matches only) OR 1MM (one match with 1 mismatched base)\n"; + exitWithError(errOut.str(),std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; + + + CBmatchWL.mm1 = false; + CBmatchWL.mm1_multi = false; + CBmatchWL.mm1_multi_pc = false; + CBmatchWL.mm1_multi_Nbase = false; + CBmatchWL.oneExact = false; //if true, for a CB matching with 1 mismatch to a WL-CB, requires at least one other read to match this WL-CB. + //this is true for all options except pseudocount + CBmatchWL.ParseBio_ED3 = false; + + if (CBmatchWL.type=="Exact") { + CBmatchWL.oneExact=true; + } else if (CBmatchWL.type=="1MM") { + CBmatchWL.mm1=true; + CBmatchWL.oneExact=true; + } else if (CBmatchWL.type=="1MM_multi") { + CBmatchWL.mm1=true; + CBmatchWL.mm1_multi=true; + CBmatchWL.oneExact=true; + } else if (CBmatchWL.type=="1MM_multi_pseudocounts") { + CBmatchWL.mm1=true; + CBmatchWL.mm1_multi=true; + CBmatchWL.mm1_multi_pc=true; + } else if (CBmatchWL.type=="1MM_multi_Nbase_pseudocounts") { + CBmatchWL.mm1=true; + CBmatchWL.mm1_multi=true; + CBmatchWL.mm1_multi_pc=true; + CBmatchWL.mm1_multi_Nbase = true; + } else if (CBmatchWL.type=="ParseBio_ED3") { + CBmatchWL.ParseBio_ED3=true; + } else { + exitWithError("EXITING because of fatal PARAMETERS error: unrecognized option in --soloCBmatchWLtype " +CBmatchWL.type + "\nSOLUTION: use allowed options: Exact or 1MM or 1MM_multi or 1MM_multi_pseudocounts 1MM_multi_Nbase_pseudocounts\n", + std::cerr, pP->inOut->logMain, EXIT_CODE_PARAMETER, *pP); + }; +}; \ No newline at end of file diff --git a/source/ParametersSolo.h b/source/ParametersSolo.h index 3a7b42a0..b7d3a52d 100755 --- a/source/ParametersSolo.h +++ b/source/ParametersSolo.h @@ -1,42 +1,202 @@ #ifndef CODE_ParametersSolo #define CODE_ParametersSolo + +#include + #include "IncludeDefine.h" +#include "SoloBarcode.h" +#include "SoloFeatureTypes.h" class Parameters; +class ParametersSolo; + +class UMIdedup { +public: + const static uint32 tN = 6; + array typeNames { {"NoDedup", "Exact", "1MM_All", "1MM_Directional", "1MM_CR", "1MM_Directional_UMItools"} }; + enum typeI : int32 { NoDedup=0, Exact=1, All=2, Directional=3, CR=4, Directional_UMItools=5 }; + + struct { + uint32_t N; + array B; + bool &NoDedup=B[0], &Exact=B[1], &All=B[2], &Directional=B[3], &CR=B[4], &Directional_UMItools=B[5]; + } yes; + + struct { + //uint32_t N; + array I; + uint32_t &NoDedup=I[0], &Exact=I[1], &All=I[2], &Directional=I[3], &CR=I[4], &Directional_UMItools=I[5]; + uint32_t main; //index for SAM/stats/filtering output + } countInd; //index in the countCellGennUMI + + vector typesIn; //UMIdedup types from user options + vector types; //the above converted to typeI numbers + int32 typeMain; //the type to be used in SAM/stats/filtering output - for now just types[0] + + void initialize(ParametersSolo *pS); + +//protected: +// int it; +}; + +class MultiMappers { +public: + const static uint32 tN = 5; + array typeNames { {"Unique", "Uniform", "Rescue", "PropUnique", "EM"} }; + enum typeI : int32 { Unique=0, Uniform=1, Rescue=2, PropUnique=3, EM=4 }; + + struct { + bool multi; //if multimappers are requested + uint32_t N; + array B; + bool &Unique=B[0], &Uniform=B[1], &Rescue=B[2], &PropUnique=B[3], &EM=B[4] ; + } yes; + + struct { + //uint32_t N; + array I; + uint32_t &Unique=I[0], &Uniform=I[1], &Rescue=I[2], &PropUnique=I[3], &EM=I[4]; + uint32_t main; //index for SAM/stats/filtering output + } countInd; //index in the countCellGennUMI + + vector typesIn; //UMIdedup types from user options + vector types; //the above converted to typeI numbers + int32 typeMain; //the type to be used in SAM/stats/filtering output - for now just types[0] + + void initialize(ParametersSolo *pS); +}; class ParametersSolo { public: + Parameters *pP; + bool yes; + //chemistry, library etc string typeStr; - int type; - uint32 cbS,cbL; //cell barcode start,length - uint32 umiS,umiL; //umi start,length - uint32 bL; //total barcode length - string soloCBwhitelist; - std::vector cbWL; - bool cbWLyes; + enum SoloTypes : int32 {None=0, CB_UMI_Simple=1, CB_UMI_Complex=2, CB_samTagOut=3, SmartSeq=4}; + SoloTypes type; string strandStr; - int32 strand; + int32 strand; + + uint32 barcodeRead, barcodeReadIn;//which read is the barcode read = 0,1,2? + uint32 barcodeStart, barcodeEnd;//start/end of barcode sequence on barcodeRead + bool barcodeReadSeparate; + + //simple barcodes + uint32 cbS, cbL; //cell barcode start,length + uint32 umiS, umiL; //umi start,length + uint32 bL, cbumiL; //total barcode sequene length, CB+UMI length. Former does may not be equal to the latter + + vector cbPositionStr; + string umiPositionStr; + + //complex barcodes + vector cbV; + SoloBarcode umiV; //single UMI + bool adapterYes; //anchor? + string adapterSeq; //anchor sequence + uint32 adapterMismatchesNmax;//max number of mismatches in the anchor + + //input from SAM files + vector samAtrrBarcodeSeq, samAtrrBarcodeQual; + + //whitelist - general + uint64 cbWLsize; + bool cbWLyes; + vector soloCBwhitelist; + vector cbWL; + vector cbWLstr; + + MultiMappers multiMap; + //features - const static vector featureNames; - vector featureIn; - vector features, featureInd; - uint32 nFeatures; - bool featureYes[3]; //which features are requested + vector featureIn;//string of requested features + vector features; + uint32 nFeatures;//=features.size(), number of requested features + + int32 featureFirst; //which feature is the first on the list + array featureYes; //which features are requested + array readInfoYes;//which features will need readInfo (for now only Gene and GeneFull) + array readIndexYes;//which features will need recording of readIndex (for now only Gene and GeneFull, for multimappers) + array featureInd;//index of each feature - skips unrequested features + //filtering char QSbase,QSmax;//quality score base and cutoff + + #ifdef MATCH_CellRanger + double cbMinP;//for CBs with non-exact matching to WL, min posterior probability + #else float cbMinP;//for CBs with non-exact matching to WL, min posterior probability - //algorithms - vector umiDedup; - vector umiDedupColumns; - vector umiDedupYes; + #endif + + //cell filtering + struct { + vector type; + uint32 topCells; + + struct { + double nExpectedCells; + double maxPercentile; + double maxMinRatio; + } knee; + + struct { + uint32 indMin, indMax; //min/max cell index, sorted by UMI counts,for empty cells + uint32 umiMin; + double umiMinFracMedian; + uint32 candMaxN; + double FDR; + uint32 simN; + } eDcr;//EmptyDrops-CellRanger + + } cellFilter; + + //CB match + struct { + string type; + bool mm1; //1 mismatch allowed + bool mm1_multi; //1 mismatch, multiple matches to WL allowed + bool oneExact; //CBs require at least one exact match + bool mm1_multi_pc; //use psedocounts while calculating probabilities of multi-matches + bool mm1_multi_Nbase; //allow multimatching to WL for CBs with N-bases + bool ParseBio_ED3; //allow EditDistance <=3 + } CBmatchWL; + + //UMIdedup + UMIdedup umiDedup; + + //multi-gene umi + struct { + vector type; + bool MultiGeneUMI = false; + bool MultiGeneUMI_All = false; + bool yes = false; //true for non-CR + bool MultiGeneUMI_CR = false; + } umiFiltering; + + //clusters + string clusterCBfile; + //output - vector outFileNames; + vector outFileNames; + struct { + string featuresGeneField3; + } outFormat; + + bool samAttrYes;//post-processed SAM attributes: error-corrected CB and UMI + int32 samAttrFeature;//which feature to use for error correction + + //processing + uint32 redistrReadsNfiles; //numer of files to resditribute reads into + //constants uint32 umiMaskLow, umiMaskHigh; //low/high half bit-mask or UMIs void initialize(Parameters *pPin); -private: - Parameters *pP; + void umiSwapHalves(uint32 &umi); + void complexWLstrings(); + void cellFiltering(); + + void init_CBmatchWL(); }; #endif diff --git a/source/Parameters_openReadsFiles.cpp b/source/Parameters_openReadsFiles.cpp index d26ca949..1f96363a 100644 --- a/source/Parameters_openReadsFiles.cpp +++ b/source/Parameters_openReadsFiles.cpp @@ -2,22 +2,14 @@ #include "ErrorWarning.h" #include #include -void Parameters::openReadsFiles() { - string readFilesCommandString(""); - if (readFilesCommand.at(0)=="-") { - if (readFilesIn.at(0).find(',')readIn[ii].is_open() ) inOut->readIn[ii].close(); - string rfName=(readFilesPrefix=="-" ? "" : readFilesPrefix)+readFilesIn.at(ii); + string rfName=readFilesPrefixFinal + readFilesIn.at(ii); inOut->readIn[ii].open(rfName.c_str()); //try to open the Sequences file right away, exit if failed if (inOut->readIn[ii].fail()) { @@ -30,14 +22,20 @@ void Parameters::openReadsFiles() { vector readsCommandFileName; - for (uint imate=0;imatelogMain, EXIT_CODE_FIFO, *this); + }; - inOut->logMain << "\n Input read files for mate "<< imate+1 <<", from input string " << readFilesIn.at(imate) <logMain << "\n Input read files for mate "<< imate+1 <<" :\n"; readsCommandFileName.push_back(outFileTmp+"/readsCommand_read" + to_string(imate+1)); fstream readsCommandFile( readsCommandFileName.at(imate).c_str(), ios::out); @@ -49,24 +47,28 @@ void Parameters::openReadsFiles() { }; readsCommandFile << "exec > \""< "+ outFileTmp+"/readFilesIn.info 2>&1").c_str()) !=0 ) + warningMessage(" Could not ls " + readFilesNames[imate][ifile], std::cerr, inOut->logMain, *this); - system(("ls -lL " + rfName + " > "+ outFileTmp+"/readFilesIn.info 2>&1").c_str()); ifstream readFilesIn_info((outFileTmp+"/readFilesIn.info").c_str()); inOut->logMain <logMain, EXIT_CODE_PARAMETER, *this); + }; + rftry.close(); + }; + + readsCommandFile <<"echo FILE "<< ifile << "\n"; + readsCommandFile << readFilesCommandString <<" "<< ("\""+readFilesNames[imate][ifile]+"\"") <<"\n"; + }; readsCommandFile.flush(); readsCommandFile.seekg(0,ios::beg); @@ -96,30 +98,14 @@ void Parameters::openReadsFiles() { readFilesCommandPID[imate]=PID; }; -// system((("\""+readsCommandFileName.at(imate)+"\"") + " & ").c_str()); inOut->readIn[imate].open(readFilesInTmp.at(imate).c_str()); }; - if (readFilesIn.size()==2 && readFilesNames.at(0).size() != readFilesNames.at(1).size()) { - ostringstream errOut; - errOut <<"EXITING: because of fatal INPUT ERROR: number of input files for mate1: "<logMain, EXIT_CODE_PARAMETER, *this); - }; - if (outSAMattrRG.size()>1 && outSAMattrRG.size()!=readFilesN) { - ostringstream errOut; - errOut <<"EXITING: because of fatal INPUT ERROR: number of input read files: "<logMain, EXIT_CODE_PARAMETER, *this); - } else if (outSAMattrRG.size()==1) {//use the same read group for all files - for (uint32 ifile=1;ifile +#include +#include "serviceFuns.cpp" + +void Parameters::readFilesInit() +{//initialize read files - but do not open yet + + if (readFilesType.at(0) == "Fastx") { + readFilesTypeN=1; + } else if (readFilesType.at(0) == "SAM"){ + readFilesTypeN=10; + readFiles.samAttrKeepAll = false; + readFiles.samAttrKeepNone = false; + if (readFiles.samAttrKeepIn.at(0) == "All") { + readFiles.samAttrKeepAll = true; + } else if (readFiles.samAttrKeepIn.at(0) == "None") { + readFiles.samAttrKeepNone = true; + } else { + for (auto &tag: readFiles.samAttrKeepIn) { + if (tag.size()!=2) { + exitWithError("EXITING because of FATAL PARAMETER ERROR: each SAM tags in --readFilesSAMtagsKeep should contain two letters\n\ + SOLUTION: specify only two-letter tags in --readFilesSAMtagsKeep.", + std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + //array taga = {tag[0], tag[1]}; + uint16_t tagn = * ( (uint16_t*) tag.c_str() ); + readFiles.samAttrKeep.insert(tagn); + }; + }; + } else { + ostringstream errOut; + errOut <<"EXITING because of FATAL INPUT ERROR: unknown/unimplemented value for --readFilesType: "<logMain, EXIT_CODE_PARAMETER, *this); + }; + + readFilesPrefixFinal=(readFilesPrefix=="-" ? "" : readFilesPrefix); + + if (readFilesManifest[0]=="-") {//no manifest, file names in readFilesIn + readFilesNames.resize(readFilesIn.size()); + + for (uint32 imate=0; imate0 && readFilesNames[imate].size() != readFilesNames[imate-1].size() ) { + ostringstream errOut; + errOut <<"EXITING: because of fatal INPUT ERROR: number of input files for mate" << imate+1 <<"="<< readFilesNames[imate].size() <<" is not equal to that for mate"<< imate-1 <<"="<< readFilesNames[imate-1].size() <<"\n"; + errOut <<"Make sure that the number of files in --readFilesIn is the same for both mates\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + + for ( auto &fn : readFilesNames[imate] ) + fn = readFilesPrefixFinal + fn; //add prefix + }; + + readFilesN = readFilesNames[0].size(); + + //read groups + if (outSAMattrRGline.at(0)!="-") { + string linefull; + for (uint ii=0;ii0) ++ii;//skip comma + outSAMattrRGlineSplit.push_back(outSAMattrRGline.at(ii)); //start new RG line with the first field which must be ID:xxx + if (outSAMattrRGlineSplit.back().substr(0,3)!="ID:") { + ostringstream errOut; + errOut <<"EXITING because of FATAL INPUT ERROR: the first word of a line from --outSAMattrRGline="<logMain, EXIT_CODE_PARAMETER, *this); + }; + outSAMattrRG.push_back(outSAMattrRGlineSplit.back().substr(3)); //this adds the ID field + } else {//keep adding fields to this RG line, until the next comma + outSAMattrRGlineSplit.back()+="\t" + outSAMattrRGline.at(ii); + }; + }; + }; + + if (outSAMattrRG.size()>1 && outSAMattrRG.size()!=readFilesN) { + ostringstream errOut; + errOut <<"EXITING: because of fatal INPUT ERROR: number of input read files: "<< readFilesN << " does not agree with number of read group RG entries: "<< outSAMattrRG.size() <<"\n"; + errOut <<"Make sure that the number of RG lines in --outSAMattrRGline is equal to either 1, or the number of input read files in --readFilesIn\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + } else if (outSAMattrRG.size()==1) {//use the same read group for all files + for (uint32 ifile=1; ifile=rfMline.size()) + continue; //skip blank lines + + uint32 itab1=0, itab2=0; + for (uint32 imate=0; imate<2; imate++) {//SE manifest 2nd column contains "-" + itab2=rfMline.find('\t',itab1); + if (itab2>=rfMline.size()) { + ostringstream errOut; + errOut <<"EXITING because of FATAL INPUT FILE error: readFileManifest file " << readFilesManifest[0] << " has to contain at least 3 tab separated columns\n"; + errOut <<"SOLUTION: fix the formatting of the readFileManifest file: Read1 Read2 ReadGroup. For single-end reads, use - in the 2nd column.\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_INPUT_FILES, *this); + }; + readFilesNames[imate].push_back( readFilesPrefixFinal + rfMline.substr(itab1,itab2-itab1) ); + itab1=itab2+1; + + inOut->logMain << readFilesNames[imate].back() <<'\t'; + }; + + outSAMattrRGlineSplit.push_back(rfMline.substr(itab2+1)); + + if (outSAMattrRGlineSplit.back().substr(0,3)!="ID:") + outSAMattrRGlineSplit.back().insert(0,"ID:"); + + itab2=outSAMattrRGlineSplit.back().find('\t'); + outSAMattrRG.push_back(outSAMattrRGlineSplit.back().substr(3,itab2-3)); + + inOut->logMain << outSAMattrRGlineSplit.back() <<'\n'; + + }; + rfM.close(); + + readNends = ( readFilesNames[1][0].back()=='-' ? 1 : 2); + readFilesNames.resize(readNends);//resize if readFilesN=1 + readFilesN = readFilesNames[0].size(); + }; + + inOut->logMain << "Number of fastq files for each mate = " << readFilesN << endl; + + readFilesCommandString=""; + if (readFilesCommand.at(0)=="-") { + if (readFilesN>1) + readFilesCommandString="cat ";//concatenate multiple files + } else { + for (uint ii=0; iilogMain, EXIT_CODE_PARAMETER, *this); + }; + }; + + readNmates=readNends; //this may be changed later if one of the reads is barcode rea +}; diff --git a/source/Parameters_readSAMheader.cpp b/source/Parameters_readSAMheader.cpp index b13227eb..2cf3acae 100644 --- a/source/Parameters_readSAMheader.cpp +++ b/source/Parameters_readSAMheader.cpp @@ -18,7 +18,13 @@ void Parameters::readSAMheader(const string readFilesCommandString, const vector string tmpFifo=outFileTmp+"tmp.fifo.header"; remove(tmpFifo.c_str()); - mkfifo(tmpFifo.c_str(), S_IRUSR | S_IWUSR ); + if (mkfifo(tmpFifo.c_str(), S_IRUSR | S_IWUSR ) != 0) { + exitWithError("Exiting because of *FATAL ERROR*: could not create FIFO file " + tmpFifo + "\n" + + "SOLUTION: check the if run directory supports FIFO files.\n" + + "If run partition does not support FIFO (e.g. Windows partitions FAT, NTFS), " + + "re-run on a Linux partition, or point --outTmpDir to a Linux partition.\n" + , std::cerr, inOut->logMain, EXIT_CODE_FIFO, *this); + }; ifstream tmpFifoIn; for (uint32 ii=0; ii vAttr1; + if (outSAMattributes.at(0)=="None") { + } else if (outSAMattributes.at(0)=="All"){ + vAttr1={"NH","HI","AS","nM","NM","MD","jM","jI","MC","ch"}; + } else if (outSAMattributes.at(0)=="Standard"){ + vAttr1={"NH","HI","AS","nM"}; + } else { + vAttr1=outSAMattributes; + }; + + for (uint ii=0;iilogMain << "WARNING --outSAMattributes contains XS, therefore STAR will use --outSAMstrandField intronMotif" <logMain, EXIT_CODE_PARAMETER, *this); + }; + }; + + if (!var.yes && (outSAMattrPresent.vA | outSAMattrPresent.vG)) { + ostringstream errOut; + errOut <<"EXITING because of fatal PARAMETER error: --outSAMattributes contains vA and/or vG tag(s), but --varVCFfile is not set\n"; + errOut <<"SOLUTION: re-run STAR with a --varVCFfile option, or without vA/vG tags in --outSAMattributes\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + + if (!wasp.yes && outSAMattrPresent.vW) { + ostringstream errOut; + errOut <<"EXITING because of fatal PARAMETER error: --outSAMattributes contains vW tag, but --waspOutputMode is not set\n"; + errOut <<"SOLUTION: re-run STAR with a --waspOutputMode option, or without vW tags in --outSAMattributes\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + + if (outSAMattrRGline[0]!="-" && !outSAMattrPresent.RG) { + outSAMattrOrder.push_back(ATTR_RG); + outSAMattrOrderQuant.push_back(ATTR_RG); + outSAMattrPresent.RG=true; + inOut->logMain << "WARNING --outSAMattrRG defines a read group, therefore STAR will output RG attribute" <logMain, EXIT_CODE_PARAMETER, *this); + }; + + if (outSAMstrandField.type==1 && !outSAMattrPresent.XS) { + outSAMattrOrder.push_back(ATTR_XS); + inOut->logMain << "WARNING --outSAMstrandField=intronMotif, therefore STAR will output XS attribute" <logMain << "WARNING --waspOutputMode is set, therefore STAR will output vW attribute" < 100 + samAttrRequiresBAM(outSAMattrPresent.ch, "ch"); + samAttrRequiresBAM(outSAMattrPresent.CR, "CR"); + samAttrRequiresBAM(outSAMattrPresent.CY, "CY"); + samAttrRequiresBAM(outSAMattrPresent.UR, "UR"); + samAttrRequiresBAM(outSAMattrPresent.UY, "UY"); + samAttrRequiresBAM(outSAMattrPresent.CB, "CB"); + samAttrRequiresBAM(outSAMattrPresent.UB, "UB"); + samAttrRequiresBAM(outSAMattrPresent.sM, "sM"); + samAttrRequiresBAM(outSAMattrPresent.sS, "sS"); + samAttrRequiresBAM(outSAMattrPresent.sQ, "sQ"); + samAttrRequiresBAM(outSAMattrPresent.rB, "rB"); + samAttrRequiresBAM(outSAMattrPresent.vG, "vG"); + samAttrRequiresBAM(outSAMattrPresent.vA, "vA"); + samAttrRequiresBAM(outSAMattrPresent.vW, "vW"); + samAttrRequiresBAM(outSAMattrPresent.GX, "GX"); + samAttrRequiresBAM(outSAMattrPresent.GN, "GN"); + + if (outSAMattrPresent.GX || outSAMattrPresent.GN) {//in case GX/GN were requested without Solo + quant.gene.yes = true; + quant.yes = true; + pSolo.samAttrFeature = SoloFeatureTypes::Gene;//TODO: this is a hack... need to perform read annotations independent of Solo + }; +}; + +void Parameters:: samAttrRequiresBAM(bool attrYes, string attrTag) { + if (!attrYes) + return; // nothing to do + if (!outBAMunsorted && !outBAMcoord) { + ostringstream errOut; + errOut <<"EXITING because of fatal PARAMETER error: --outSAMattributes contains "<< attrTag <<" tag, which requires BAM output.\n"; + errOut <<"SOLUTION: re-run STAR with --outSAMtype BAM Unsorted (and/or) SortedByCoordinate option, or without "<< attrTag <<" tag in --outSAMattributes\n"; + exitWithError(errOut.str(), std::cerr, inOut->logMain, EXIT_CODE_PARAMETER, *this); + }; + + if (outSAMbool) + inOut->logMain << "WARNING: --outSAMattributes contains "<< attrTag <<" tag. It will be output into BAM file(s), but not SAM file.\n"; +}; \ No newline at end of file diff --git a/source/ReadAlign.cpp b/source/ReadAlign.cpp old mode 100644 new mode 100755 index 3c15ef0c..e2a8a3c8 --- a/source/ReadAlign.cpp +++ b/source/ReadAlign.cpp @@ -4,14 +4,9 @@ #include "ReadAlign.h" ReadAlign::ReadAlign (Parameters& Pin, Genome &genomeIn, Transcriptome *TrIn, int iChunk) - : mapGen(genomeIn), P(Pin), chunkTr(TrIn) + : mapGen(genomeIn), genOut(*genomeIn.genomeOut.g), P(Pin), chunkTr(TrIn) { - readNmates=P.readNmates; - winBin = new uintWinBin* [2]; - winBin[0] = new uintWinBin [P.winBinN]; - winBin[1] = new uintWinBin [P.winBinN]; - memset(winBin[0],255,sizeof(winBin[0][0])*P.winBinN); - memset(winBin[1],255,sizeof(winBin[0][0])*P.winBinN); + readNmates=P.readNmates; //not readNends //RNGs rngMultOrder.seed(P.runRNGseed*(iChunk+1)); rngUniformReal0to1=std::uniform_real_distribution (0.0, 1.0); @@ -19,30 +14,42 @@ ReadAlign::ReadAlign (Parameters& Pin, Genome &genomeIn, Transcriptome *TrIn, in if ( P.quant.trSAM.yes ) { alignTrAll=new Transcript [P.alignTranscriptsPerReadNmax]; }; - //split - splitR=new uint*[3]; - splitR[0]=new uint[P.maxNsplit]; splitR[1]=new uint[P.maxNsplit]; splitR[2]=new uint[P.maxNsplit]; - //alignments - PC=new uiPC[P.seedPerReadNmax]; - WC=new uiWC[P.alignWindowsPerReadNmax]; - nWA=new uint[P.alignWindowsPerReadNmax]; - nWAP=new uint[P.alignWindowsPerReadNmax]; - WALrec=new uint[P.alignWindowsPerReadNmax]; - WlastAnchor=new uint[P.alignWindowsPerReadNmax]; -#ifdef COMPILE_FOR_LONG_READS - swWinCov = new uint[P.alignWindowsPerReadNmax]; - scoreSeedToSeed = new intScore [P.seedPerWindowNmax*(P.seedPerWindowNmax+1)/2]; - scoreSeedBest = new intScore [P.seedPerWindowNmax]; - scoreSeedBestInd = new uint [P.seedPerWindowNmax]; - scoreSeedBestMM = new uint [P.seedPerWindowNmax]; - seedChain = new uint [P.seedPerWindowNmax]; -#endif + if (P.pGe.gType==101) {//SuperTranscriptome + splGraph = new SpliceGraph(*mapGen.superTr, P, this); + } else {//standard map algorithm: + winBin = new uintWinBin* [2]; + winBin[0] = new uintWinBin [P.winBinN]; + winBin[1] = new uintWinBin [P.winBinN]; + memset(winBin[0],255,sizeof(winBin[0][0])*P.winBinN); + memset(winBin[1],255,sizeof(winBin[0][0])*P.winBinN); + //split + splitR=new uint*[3]; + splitR[0]=new uint[P.maxNsplit]; splitR[1]=new uint[P.maxNsplit]; splitR[2]=new uint[P.maxNsplit]; + //alignments + PC=new uiPC[P.seedPerReadNmax]; + WC=new uiWC[P.alignWindowsPerReadNmax]; + nWA=new uint[P.alignWindowsPerReadNmax]; + nWAP=new uint[P.alignWindowsPerReadNmax]; + WALrec=new uint[P.alignWindowsPerReadNmax]; + WlastAnchor=new uint[P.alignWindowsPerReadNmax]; + + WA=new uiWA*[P.alignWindowsPerReadNmax]; + for (uint ii=0;ii #include class ReadAlign { public: - //methods ReadAlign (Parameters& Pin, Genome &genomeIn, Transcriptome *TrIn, int iChunk);//allocate arrays int oneRead(); - //vars - Genome &mapGen; //mapped-to-genome structure + Genome &mapGen, &genOut; //mapped-to-genome structure - uint iRead; + uint64 iRead, iReadAll; char **Read1; Stats statsRA; //mapping statistics @@ -41,9 +42,36 @@ class ReadAlign { uint outFilterMismatchNmaxTotal; uint Lread, readLength[MAX_N_MATES], readLengthOriginal[MAX_N_MATES], readLengthPair, readLengthPairOriginal; + string readBarcodeSeq, readBarcodeQual; //Solo barcode sequence + intScore maxScoreMate[MAX_N_MATES]; - uint readFilesIndex; + uint32 readFilesIndex; + + //quality histogram + array,MAX_N_MATES> qualHist; + + //transcripts (aligns) + uint nW; + uint *nWinTr; //number of recorded transcripts per window + Transcript trA, trA1, *trInit; //transcript, best tr, next best tr, initialized tr + Transcript ***trAll; //all transcripts for all windows + Transcript *trArray; //linear array of transcripts to store all of them from all windows + Transcript **trArrayPointer; //linear array of transcripts to store all of them from all windows + + uint64 nTr; // number of transcripts called + Transcript *trMult[MAX_N_MULTMAP];//selected alignments - to the mapGen + Transcript *trBest;//bset transcripts + + struct { + bool yes; + uint64 alN; + Transcript **alMult;//multimapping transcripts - transformed to output genome + Transcript *alBest;//best align + } alignsGenOut; + + + Transcript *alignTrAll;//alignments to transcriptome ReadAlign *waspRA; //ReadAlign for alternative WASP alignment int waspType, waspType1; //alignment ASE-WASP type and @@ -51,8 +79,18 @@ class ReadAlign { ReadAlign *peMergeRA; //ReadAlign for merged PE mates ChimericDetection *chimDet; + void peOverlapChimericSEtoPE(const Transcript *seTrIn1, const Transcript *seTrIn2, Transcript *peTrOut1, Transcript *peTrOut2); SoloRead *soloRead; //counts reads per CB per and outputs CB/UMI/gene into file, per thread + + SpliceGraph *splGraph; + + vector> clipMates; + + //input,output + char** outBAMoneAlign; + uint* outBAMoneAlignNbytes; + int alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint trChrStart, uint mateChr, uint mateStart, char mateStrand, int unmapType, bool *mateMap, vector outSAMattrOrder, char** outBAMarray, uint* outBAMarrayN); private: Parameters& P; //pointer to the parameters, will be initialized on construction @@ -69,28 +107,19 @@ class ReadAlign { //input,output - char** outBAMoneAlign; - uint* outBAMoneAlignNbytes; - ostringstream samStreamCIGAR, samStreamSJmotif, samStreamSJintron; vector matesCIGAR; intScore *scoreSeedToSeed, *scoreSeedBest; uint *scoreSeedBestInd, *seedChain, *scoreSeedBestMM; - bool outFilterPassed; //true if alignment passed all filter and is output to SAM/BAM - -// StatsAll *statsRA; - - //transcript - Transcript* trArray; //linear array of transcripts to store all of them from all windows - Transcript** trArrayPointer; //linear array of transcripts to store all of them from all windows + bool outFilterBySJoutPass; //true if alignment passed all filters and is output + bool outSAMfilterPass; //true if alignment passed SAM filter //read - uint iReadAll, iMate; + uint64 iMate; char readFilter; //Illumina not passed Y/N bool revertStrand; //what to do with the strand, according to strandType and iMate - uint clip3pNtotal[MAX_N_MATES], clip5pNtotal[MAX_N_MATES], clip3pAdapterN[MAX_N_MATES]; //total number of trimmed bases from 5p,3p int readFileType; //file type: 1=fasta; 2=fastq vectorreadNameExtra; @@ -100,7 +129,6 @@ class ReadAlign { char** Qual0; char** readNameMates; char* readName; - char** Qual1; //modified QSs for scoring uint readNmates; //split @@ -120,7 +148,7 @@ class ReadAlign { int unmapType; //marker for why a read is unmapped uint mapMarker; //alignment marker (typically, if there is something wrong) - uint nA, nP, nW, nWall, nUM[2]; //number of all alignments, pieces, windows, U/M, + uint nA, nP, nWall, nUM[2]; //number of all alignments, pieces, windows, U/M, uint *nWA, *nWAP, *WALrec, *WlastAnchor; //number of alignments per window, per window per piece, min recordable length per window bool *WAincl; //alginment inclusion mask @@ -128,13 +156,9 @@ class ReadAlign { char *swT; uint storedLmin, uniqLmax, uniqLmaxInd, multLmax, multLmaxN, multNmin, multNminL, multNmax, multNmaxL; - uint nTr, nTrMate; // number of transcripts called intScore maxScore;//maximum alignment score - - Transcript trA, trA1, *trBest, *trInit; //transcript, best tr, next best tr, initialized tr - Transcript ***trAll; //all transcripts for all windows - uint *nWinTr; //number of recorded transcripts per window - + bool mateMapped[2]; + //old chimeric detection uint chimN, chimRepeat, chimStr; int chimMotif; @@ -143,27 +167,30 @@ class ReadAlign { //new chimeric detection bool chimRecord; //true if chimeric aligment was detected - Transcript *alignC, *extendC, *polyAtailC; //alignment rules/conditions - - Transcript* trMult[MAX_N_MULTMAP];//multimapping transcripts - Transcript *alignTrAll;//alignments to transcriptome - struct { bool yes; uint nOv;//number of overlapping bases uint ovS;//first read base of the overlap uint mateStart[2];//mates starts in the merged read } peOv;//PE mates overlap/merge/remap structure + + //read annotations + ReadAnnotations readAnnot; + /////////////////////////////////////////////////////////////////// METHODS void resetN();//resets the counters to 0 void multMapSelect(); int mapOneRead(); + void mapOneReadSpliceGraph(); uint maxMappableLength2strands(uint pieceStart, uint pieceLength, uint iDir, uint iSA1, uint iSA2, uint& maxL, uint iFrag); void storeAligns (uint iDir, uint Shift, uint Nrep, uint L, uint indStartEnd[2], uint iFrag); bool outputTranscript(Transcript *trOut, uint nTrOut, ofstream *outBED); - uint outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint mateChr, uint mateStart, char mateStrand, int unmapType, bool *mateMapped, ostream *outStream); - int alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint trChrStart, uint mateChr, uint mateStart, char mateStrand, int unmapType, bool *mateMapped, vector outSAMattrOrder, char** outBAMarray, uint* outBAMarrayN); + + uint64 outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint mateChr, uint mateStart, char mateStrand, int unmapType, bool *mateMap, ostream *outStream); + + uint64 outputSpliceGraphSAM(Transcript const &trOut, uint nTrOut, uint iTrOut, ostream *outStream); + void samAttrNM_MD (Transcript const &trOut, uint iEx1, uint iEx2, uint &tagNM, string &tagMD); void outputTranscriptSJ(Transcript const &trOut, uint nTrOut, OutSJ *outStream, uint sjReadStartN ); @@ -177,22 +204,29 @@ class ReadAlign { void chimericDetectionOldOutput(); bool chimericDetectionMult(); void chimericDetectionPEmerged(ReadAlign &seRa); -// void chimericDetectionPEmergedTrim(); + void transformGenome(); void outputAlignments(); void calcCIGAR(Transcript const &trOut, uint nMates, uint iExMate, uint leftMate); void stitchWindowSeeds (uint iW, uint iWrec, bool *WAexcl, char *R);//stitches all seeds in one window: iW void stitchPieces(char **R, uint Lread); - uint quantTranscriptome (Transcriptome *Tr, uint nAlignG, Transcript **alignG, Transcript *alignT, vector &readTranscripts, set &readTrGenes); + uint quantTranscriptome (Transcriptome *Tr, uint nAlignG, Transcript **alignG, Transcript *alignT); void copyRead(ReadAlign&); void waspMap(); void peOverlapMergeMap(); void peMergeMates(); void peOverlapSEtoPE(ReadAlign &seRA); - + + //output alignments functions + void outFilterBySJout(); + void outReadsUnmapped(); + void spliceGraphWriteSAM(); + void alignedAnnotation(); + void writeSAM(uint64 nTrOutSAM, Transcript **trOutSAM, Transcript *trBestSAM); + void recordSJ(uint64 nTrO, Transcript **trO, OutSJ *cSJ); }; diff --git a/source/ReadAlignChunk.cpp b/source/ReadAlignChunk.cpp index caea15bc..8f7f180b 100644 --- a/source/ReadAlignChunk.cpp +++ b/source/ReadAlignChunk.cpp @@ -17,10 +17,10 @@ ReadAlignChunk::ReadAlignChunk(Parameters& Pin, Genome &genomeIn, Transcriptome RA->iRead=0; - chunkIn=new char* [P.readNmates]; - readInStream=new istringstream* [P.readNmates]; -// readInStream=new istringstream* [P.readNmates]; - for (uint ii=0;iioutBAMquant=NULL; }; - chunkOutSJ=new OutSJ (P.limitOutSJcollapsed, P, mapGen); - chunkOutSJ1=new OutSJ (P.limitOutSJcollapsed, P, mapGen); + if (P.outSJ.yes) { + chunkOutSJ = new OutSJ (P.limitOutSJcollapsed, P, mapGen); + RA->chunkOutSJ = chunkOutSJ; + } else { + RA->chunkOutSJ = NULL; + }; - RA->chunkOutSJ=chunkOutSJ; - RA->chunkOutSJ1=chunkOutSJ1; + if (P.outFilterBySJoutStage == 1) { + chunkOutSJ1 = new OutSJ (P.limitOutSJcollapsed, P, mapGen); + RA->chunkOutSJ1 = chunkOutSJ1; + } else { + RA->chunkOutSJ1 = NULL; + }; + + + if (P.pCh.segmentMin>0) { if (P.pCh.out.samOld) { @@ -77,13 +88,15 @@ ReadAlignChunk::ReadAlignChunk(Parameters& Pin, Genome &genomeIn, Transcriptome chunkFstreamOpen(P.outFileTmp + "/Chimeric.out.junction.thread", iChunk, *RA->chunkOutChimJunction); }; }; + if (P.outReadsUnmapped=="Fastx" ) { - chunkFstreamOpen(P.outFileTmp + "/Unmapped.out.mate1.thread",iChunk, RA->chunkOutUnmappedReadsStream[0]); - if (P.readNmatesIn==2) chunkFstreamOpen(P.outFileTmp + "/Unmapped.out.mate2.thread",iChunk, RA->chunkOutUnmappedReadsStream[1]); + for (uint32 imate=0; imate < P.readNends; imate++) + chunkFstreamOpen(P.outFileTmp + "/Unmapped.out.mate"+ to_string(imate) +".thread",iChunk, RA->chunkOutUnmappedReadsStream[imate]); }; + if (P.outFilterType=="BySJout") { chunkFstreamOpen(P.outFileTmp + "/FilterBySJoutFiles.mate1.thread",iChunk, RA->chunkOutFilterBySJoutFiles[0]); - if (P.readNmates==2) chunkFstreamOpen(P.outFileTmp + "/FilterBySJoutFiles.mate2.thread",iChunk, RA->chunkOutFilterBySJoutFiles[1]); + if (P.readNends==2) chunkFstreamOpen(P.outFileTmp + "/FilterBySJoutFiles.mate2.thread",iChunk, RA->chunkOutFilterBySJoutFiles[1]); //here we do not output barcode read }; if (P.wasp.yes) { @@ -94,6 +107,8 @@ ReadAlignChunk::ReadAlignChunk(Parameters& Pin, Genome &genomeIn, Transcriptome delete RA->peMergeRA->chunkOutChimJunction; RA->peMergeRA->chunkOutChimJunction=RA->chunkOutChimJunction;//point to the same out-stream RA->peMergeRA->chimDet->ostreamChimJunction=RA->peMergeRA->chunkOutChimJunction; + RA->peMergeRA->outBAMunsorted=RA->outBAMunsorted; + RA->peMergeRA->outBAMcoord=RA->outBAMcoord; }; }; diff --git a/source/ReadAlignChunk.h b/source/ReadAlignChunk.h index c21b0b99..50bb3d8e 100644 --- a/source/ReadAlignChunk.h +++ b/source/ReadAlignChunk.h @@ -17,12 +17,14 @@ class ReadAlignChunk {//chunk of reads and alignments Transcriptome *chunkTr; char **chunkIn; //space for the chunk of input reads + array chunkInSizeBytesTotal; + char *chunkOutBAM, *chunkOutBAM1;//space for the chunk of output SAM OutSJ *chunkOutSJ, *chunkOutSJ1; BAMoutput *chunkOutBAMcoord, *chunkOutBAMunsorted, *chunkOutBAMquant; Quantifications *chunkQuants; - + istringstream** readInStream; ostringstream* chunkOutBAMstream; ofstream chunkOutBAMfile; diff --git a/source/ReadAlignChunk_mapChunk.cpp b/source/ReadAlignChunk_mapChunk.cpp index 3e81c3a7..bd4088c7 100644 --- a/source/ReadAlignChunk_mapChunk.cpp +++ b/source/ReadAlignChunk_mapChunk.cpp @@ -5,12 +5,19 @@ #include SAMTOOLS_BGZF_H void ReadAlignChunk::mapChunk() {//map one chunk. Input reads stream has to be setup in RA->readInStream[ii] + + for (uint32 im=0; im<1; im++) {//hardcoded mate 1 5p onyl for now + RA->clipMates[im][0].clipChunk(chunkIn[im], chunkInSizeBytesTotal[im]); + }; + RA->statsRA.resetN(); - for (uint ii=0;iireadInStream[ii]->clear(); RA->readInStream[ii]->seekg(0,ios::beg); }; + + if ( P.outSAMorder == "PairedKeepInputOrder" && P.runThreadN>1 ) {//open chunk file ostringstream name1(""); @@ -42,11 +49,13 @@ void ReadAlignChunk::mapChunk() {//map one chunk. Input reads stream has to be s if ( P.outSAMorder == "PairedKeepInputOrder" && P.runThreadN>1 ) {//output chunks into separate files chunkOutBAMfile.write(chunkOutBAM,chunkOutBAMtotal); chunkOutBAMfile.clear(); //in case 0 bytes were written which could set fail bit + //chunkOutBAMfile.flush(); //not needed } else {//standard way, directly into Aligned.out.sam file //SAM output if (P.runThreadN>1) pthread_mutex_lock(&g_threadChunks.mutexOutSAM); P.inOut->outSAM->write(chunkOutBAM,chunkOutBAMtotal); P.inOut->outSAM->clear();//in case 0 bytes were written which could set fail bit + //P.inOut->outSAM->flush(); //not needed if (P.runThreadN>1) pthread_mutex_unlock(&g_threadChunks.mutexOutSAM); }; RA->outSAMstream->seekp(0,ios::beg); //rewind the chunk storage @@ -55,7 +64,9 @@ void ReadAlignChunk::mapChunk() {//map one chunk. Input reads stream has to be s }; //collapse SJ buffer if needed - if ( chunkOutSJ->N > P.limitOutSJcollapsed ) {//this means the number of collapsed junctions is larger than the chunks size + if ( !P.outSJ.yes ) { + //do nothing + } else if ( chunkOutSJ->N > P.limitOutSJcollapsed ) {//this means the number of collapsed junctions is larger than the chunks size ostringstream errOut; errOut <<"EXITING because of fatal error: buffer size for SJ output is too small\n"; errOut <<"Solution: increase input parameter --limitOutSJoneRead\n"; @@ -71,7 +82,9 @@ void ReadAlignChunk::mapChunk() {//map one chunk. Input reads stream has to be s }; //collapse SJ1 buffer if needed - if ( chunkOutSJ1->N > P.limitOutSJcollapsed ) {//this means the number of collapsed junctions is larger than the chunks size + if ( P.outFilterBySJoutStage != 1 ) {//no outFilterBySJoutStage + //do nothing + } else if ( chunkOutSJ1->N > P.limitOutSJcollapsed ) {//this means the number of collapsed junctions is larger than the chunks size ostringstream errOut; errOut <<"EXITING because of fatal error: buffer size for SJ output is too small\n"; errOut <<"Solution: increase input parameter --limitOutSJoneRead\n"; diff --git a/source/ReadAlignChunk_processChunks.cpp b/source/ReadAlignChunk_processChunks.cpp index 8bf0fe24..611613ec 100755 --- a/source/ReadAlignChunk_processChunks.cpp +++ b/source/ReadAlignChunk_processChunks.cpp @@ -1,8 +1,12 @@ #include "ReadAlignChunk.h" -#include "GlobalVariables.h" #include "ThreadControl.h" #include "ErrorWarning.h" #include "SequenceFuns.h" +#include "GlobalVariables.h" + +inline uint64 fastqReadOneLine(ifstream &streamIn, char *arrIn); +inline void removeStringEndControl(string &str); + void ReadAlignChunk::processChunks() {//read-map-write chunks noReadsLeft=false; //true if there no more reads left in the file @@ -13,37 +17,64 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks if (P.runThreadN>1) pthread_mutex_lock(&g_threadChunks.mutexInRead); - uint chunkInSizeBytesTotal[2]={0,0}; + chunkInSizeBytesTotal={0,0}; + while (chunkInSizeBytesTotal[0] < P.chunkInSizeBytes && chunkInSizeBytesTotal[1] < P.chunkInSizeBytes && P.inOut->readIn[0].good() && P.inOut->readIn[1].good()) { char nextChar=P.inOut->readIn[0].peek(); if (P.iReadAll==P.readMapNumber) {//do not read any more reads break; + + ///////////////////////////////////////////////////////////////////////////////////// SAM } else if (P.readFilesTypeN==10 && P.inOut->readIn[0].good() && P.outFilterBySJoutStage!=2) {//SAM input && not eof && not 2nd stage - string str1; if (nextChar=='@') {//with SAM input linest that start with @ are headers - getline(P.inOut->readIn[0], str1); //read line and skip it + P.inOut->readIn[0].ignore(DEF_readNameSeqLengthMax,'\n'); //read line and skip it continue; }; + string str1; P.inOut->readIn[0] >> str1; if (str1=="FILE") { newFile=true; } else { P.iReadAll++; //increment read number + uint64 flag1; + P.inOut->readIn[0] >> flag1; uint imate1=0; - for (uint imate=0;imate0) - P.inOut->readIn[0] >> str1; //for imate=0 str1 was already read - uint flag; - P.inOut->readIn[0] >>flag; //read name and flag - char passFilterIllumina=(flag & 0x800 ? 'Y' : 'N'); + for (uint imate=0;imate0) { + string str2; + uint64 flag2; + P.inOut->readIn[0] >> str2; //for imate=0 str1 was already read + P.inOut->readIn[0] >> flag2; //read name and flag + + if ( str1 != str2 ) { + ostringstream errOut; + errOut << ERROR_OUT <<" EXITING because of FATAL ERROR in input BAM file: the consecutive lines in paired-end BAM have different read IDs:\n" + << str1 <<" vs "<< str2 << '\n' + << "\n SOLUTION: fix BAM file formatting. Paired-end reads should be always consecutive lines, with exactly 2 lines per paired-end read" ; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + }; + + if (! ( ((flag1 & 0x40) && (flag2 & 0x80)) || ((flag2 & 0x40) && (flag1 & 0x80)) ) ) { + ostringstream errOut; + errOut << ERROR_OUT <<" EXITING because of FATAL ERROR in input BAM file: the consecutive lines in paired-end BAM have wrong mate FLAG bits:\n" + << str1 <<" "<< flag1 <<" vs "<< str2 <<" "<< flag2 << '\n' + << "\n SOLUTION: fix BAM file formatting. Paired-end reads should be always consecutive lines, with exactly 2 lines per paired-end read." + << " Mate1 should have 0x40 bit set in the FLAG, Mate2 should have 0x80 bit set in the FLAG"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + }; + + str1 = str2; //used below for both mates + flag1 = flag2; //used below for both mates + }; + char passFilterIllumina=(flag1 & 0x800 ? 'Y' : 'N'); if (imate==1) {//2nd line is always opposite of the 1st one imate1=1-imate1; - } else if (P.readNmates==2 && (flag & 0x80)) { + } else if (P.readNmates==2 && (flag1 & 0x80)) {//not readNends: this is SAM input imate1=1; } else { imate1=0; @@ -59,25 +90,30 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks //iReadAll, passFilterIllumina, passFilterIllumina chunkInSizeBytesTotal[imate1] += sprintf(chunkIn[imate1] + chunkInSizeBytesTotal[imate1], " %llu %c %i", P.iReadAll, passFilterIllumina, P.readFilesIndex); + string dummy; for (int ii=3; ii<=9; ii++) - P.inOut->readIn[0] >> str1; //skip fields until sequence + P.inOut->readIn[0] >> dummy; //skip fields until sequence string seq1,qual1; P.inOut->readIn[0] >> seq1 >> qual1; - if (flag & 0x10) {//sequence reverse-coomplemented + if (flag1 & 0x10) {//sequence reverse-coomplemented revComplementNucleotides(seq1); reverse(qual1.begin(),qual1.end()); }; - - getline(P.inOut->readIn[0],str1); //str1 is now all SAM attributes - chunkInSizeBytesTotal[imate1] += sprintf(chunkIn[imate1] + chunkInSizeBytesTotal[imate1], "%s\n%s\n+\n%s\n", str1.c_str(), seq1.c_str(), qual1.c_str()); + + string attrs; + getline(P.inOut->readIn[0], attrs); //rest of the SAM line: str1 is now all SAM attributes - it's added to the read ID line (1st "fastq" line) + chunkInSizeBytesTotal[imate1] += sprintf(chunkIn[imate1] + chunkInSizeBytesTotal[imate1], "%s\n%s\n+\n%s\n", attrs.c_str(), seq1.c_str(), qual1.c_str()); }; }; + + ///////////////////////////////////////////////////////////////////////////////////// FASTQ } else if (nextChar=='@') {//fastq, not multi-line P.iReadAll++; //increment read number if (P.outFilterBySJoutStage!=2) {//not the 2nd stage of the 2-stage mapping, read ID from the 1st read string readID; P.inOut->readIn[0] >> readID; + removeStringEndControl(readID); if (P.outSAMreadIDnumber) { readID="@"+to_string(P.iReadAll); }; @@ -86,49 +122,42 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks if (P.inOut->readIn[0].peek()!='\n') {//2nd field exists string field2; P.inOut->readIn[0] >> field2; - if (field2.length()>=3 && field2.at(1)==':' && field2.at(2)=='Y' && field2.at(3)==':' ) + if (field2.length()>=3 && field2[1]==':' && field2[2]=='Y' && field2[3]==':' ) passFilterIllumina='Y'; }; + + //add extra information to readID line readID += ' '+ to_string(P.iReadAll)+' '+passFilterIllumina+' '+to_string(P.readFilesIndex); //ignore the rest of the read name for both mates - for (uint imate=0; imatereadIn[imate].ignore(DEF_readNameSeqLengthMax,'\n'); - if (P.pSolo.type==1) {//record barcode sequence - string seq1; - getline(P.inOut->readIn[1],seq1); - if (seq1.size() != P.pSolo.bL && P.pSolo.bL > 0) { - ostringstream errOut; - errOut << "EXITING because of FATAL ERROR in input read file: the total length of barcode sequence is " << seq1.size() << " not equal to expected " <logMain, EXIT_CODE_INPUT_FILES, P); - }; - readID += ' ' + seq1; - P.inOut->readIn[1].ignore(DEF_readNameSeqLengthMax,'\n');//skip to the end of 3rd ("+") line - getline(P.inOut->readIn[1],seq1); //read qualities - readID += ' ' + seq1; - }; - //copy the same readID to both mates - for (uint imate=0; imatereadIn[imate].getline(chunkIn[imate] + chunkInSizeBytesTotal[imate], DEF_readNameSeqLengthMax+1 ); - chunkInSizeBytesTotal[imate] += P.inOut->readIn[imate].gcount(); - chunkIn[imate][chunkInSizeBytesTotal[imate]-1]='\n'; - }; + for (uint imate=0; imatereadIn[imate], chunkIn[imate] + chunkInSizeBytesTotal[imate]); + //sequence + chunkInSizeBytesTotal[imate] += fastqReadOneLine(P.inOut->readIn[imate], chunkIn[imate] + chunkInSizeBytesTotal[imate]); + //skip 3rd line, record '+' + P.inOut->readIn[imate].ignore(DEF_readNameSeqLengthMax, '\n'); + chunkIn[imate][chunkInSizeBytesTotal[imate]] = '+'; + chunkIn[imate][chunkInSizeBytesTotal[imate]+1] = '\n'; + chunkInSizeBytesTotal[imate] += 2; + //quality + uint64 lenIn = fastqReadOneLine(P.inOut->readIn[imate], chunkIn[imate] + chunkInSizeBytesTotal[imate]); + chunkInSizeBytesTotal[imate] += lenIn; }; } else if (nextChar=='>') {//fasta, can be multiline, which is converted to single line P.iReadAll++; //increment read number - for (uint imate=0; imatereadIn[imate].ignore(DEF_readNameSeqLengthMax,'\n'); chunkInSizeBytesTotal[imate] += sprintf(chunkIn[imate] + chunkInSizeBytesTotal[imate], " %llu %c %i \n", P.iReadAll, 'N', P.readFilesIndex); - - }; -// else {//2nd stage of 2-stage mapping -// read index and file index are already recorded with the read name, simply copy it -// P.inOut->readIn[imate].getline(chunkIn[imate] + chunkInSizeBytesTotal[imate], DEF_readNameSeqLengthMax+1 ); -// }; + + //read multi-line fasta nextChar=P.inOut->readIn[imate].peek(); - while (nextChar!='@' && nextChar!='>' && nextChar!=' ' && nextChar!='\n' && P.inOut->readIn[imate].good()) {//read multi-line fasta + while (nextChar!='@' && nextChar!='>' && nextChar!=' ' && nextChar!='\n' && P.inOut->readIn[imate].good()) { P.inOut->readIn[imate].getline(chunkIn[imate] + chunkInSizeBytesTotal[imate], DEF_readSeqLengthMax + 1 ); - if (P.inOut->readIn[imate].gcount()<2) break; //no more input - chunkInSizeBytesTotal[imate] += P.inOut->readIn[imate].gcount()-1; + if (P.inOut->readIn[imate].gcount()<2) + break; //no more input + + chunkInSizeBytesTotal[imate] += P.inOut->readIn[imate].gcount()-1; //-1 because \n was counted, bu wee need to remove it + if ( int(chunkIn[imate][chunkInSizeBytesTotal[imate]-1]) < 33 ) {//remove control char at the end if present + chunkInSizeBytesTotal[imate]--; + }; + nextChar=P.inOut->readIn[imate].peek(); }; chunkIn[imate][chunkInSizeBytesTotal[imate]]='\n'; @@ -168,7 +199,11 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks newFile=true; } else {//error ostringstream errOut; - errOut << ERROR_OUT <<" EXITING because of FATAL ERROR in input reads: unknown file format: the read ID should start with @ or > \n"; + string str1; + std::getline(P.inOut->readIn[0], str1); + errOut << ERROR_OUT <<" EXITING because of FATAL ERROR in input reads: wrong read ID line format: the read ID lines should start with @ or > \n"; + errOut << "Offending line for read # " << P.iReadAll+1 << "\n" << word1 <<" "<< str1 << "\n"; + errOut << "SOLUTION: verify and correct the input read files\n"; exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); }; }; @@ -197,13 +232,14 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks g_threadChunks.chunkInN++; }; - for (uint imate=0; imate1) pthread_mutex_unlock(&g_threadChunks.mutexInRead); } else {//read from one file per thread noReadsLeft=true; - for (uint imate=0; imatechunkOutFilterBySJoutFiles[imate].flush(); RA->chunkOutFilterBySJoutFiles[imate].seekg(0,ios::beg); RA->readInStream[imate]=& RA->chunkOutFilterBySJoutFiles[imate]; @@ -232,7 +268,7 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks if (P.runThreadN>1) pthread_mutex_lock(&g_threadChunks.mutexOutUnmappedFastx); - for (uint ii=0;iichunkOutUnmappedReadsStream[ii],P.inOut->outUnmappedReadsStream[ii], false, g_threadChunks.mutexOutUnmappedFastx); }; @@ -245,3 +281,22 @@ void ReadAlignChunk::processChunks() {//read-map-write chunks if (P.runThreadN>1) pthread_mutex_unlock(&g_threadChunks.mutexLogMain); }; +inline uint64 fastqReadOneLine(ifstream &streamIn, char *arrIn) +{ + uint64 lenIn; + streamIn.getline(arrIn, DEF_readNameSeqLengthMax+1 ); + lenIn = streamIn.gcount(); //=seqLength+1: includes \0 but not \n. We will replace \0 with \n + + if ( int(arrIn[lenIn-2]) < 33 ) {//remove control char at the end if present + --lenIn; + }; + + arrIn[lenIn-1]='\n'; //replace \0 with \n + return lenIn; //lenIn contains \n at the end +}; + +inline void removeStringEndControl(string &str) +{//removes control character (including space) from the end of the string + if (int(str.back())<33) + str.pop_back(); +}; diff --git a/source/ReadAlign_CIGAR.cpp b/source/ReadAlign_CIGAR.cpp index baf10d8b..72c91737 100644 --- a/source/ReadAlign_CIGAR.cpp +++ b/source/ReadAlign_CIGAR.cpp @@ -5,13 +5,13 @@ samStreamCIGAR.str(std::string()); uint trimL; if (Str==0 && Mate==0) { - trimL=clip5pNtotal[Mate]; + trimL=clipMates[Mate][0].clippedN; } else if (Str==0 && Mate==1) { - trimL=clip3pNtotal[Mate]; + trimL=clipMates[Mate][1].clippedN; } else if (Str==1 && Mate==0) { - trimL=clip3pNtotal[Mate]; + trimL=clipMates[Mate][1].clippedN; } else { - trimL=clip5pNtotal[Mate]; + trimL=clipMates[Mate][0].clippedN; }; uint trimL1 = trimL + trOut.exons[iEx1][EX_R] - (trOut.exons[iEx1][EX_R] // C++0x +# include "BAMfunctions.h" + +#include void ReadAlign::samAttrNM_MD (Transcript const &trOut, uint iEx1, uint iEx2, uint &tagNM, string &tagMD) { tagNM=0; tagMD=""; char* R=Read1[trOut.roStr==0 ? 0:2]; uint matchN=0; + uint32 nMM=0, nI=0, nD=0; for (uint iex=iEx1;iex<=iEx2;iex++) { for (uint ii=0;ii>14 == end>>14) return ((1<<15)-1)/7 + (beg>>14); - if (beg>>17 == end>>17) return ((1<<12)-1)/7 + (beg>>17); - if (beg>>20 == end>>20) return ((1<<9)-1)/7 + (beg>>20); - if (beg>>23 == end>>23) return ((1<<6)-1)/7 + (beg>>23); - if (beg>>26 == end>>26) return ((1<<3)-1)/7 + (beg>>26); - return 0; -}; - -int bamAttrArrayWrite(int32 attr, const char* tagName, char* attrArray ) { - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - attrArray[2]='i'; - *( (int32*) (attrArray+3))=attr; - return 3+sizeof(int32); -}; -int bamAttrArrayWrite(float attr, const char* tagName, char* attrArray ) { - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - attrArray[2]='f'; - *( (float*) (attrArray+3))=attr; - return 3+sizeof(int32); -}; -int bamAttrArrayWrite(char attr, const char* tagName, char* attrArray ) { - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - attrArray[2]='A'; - attrArray[3]=attr; - return 3+sizeof(char); -}; -int bamAttrArrayWrite(string &attr, const char* tagName, char* attrArray ) { - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - attrArray[2]='Z'; - memcpy(attrArray+3,attr.c_str(),attr.size()+1);//copy string data including \0 - return 3+attr.size()+1; -}; -int bamAttrArrayWrite(const vector &attr, const char* tagName, char* attrArray ) { - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - attrArray[2]='B'; - attrArray[3]='c'; - *( (int32*) (attrArray+4))=attr.size(); - memcpy(attrArray+4+sizeof(int32),attr.data(),attr.size());//copy array data - return 4+sizeof(int32)+attr.size(); -}; -int bamAttrArrayWrite(const vector &attr, const char* tagName, char* attrArray ) { - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - attrArray[2]='B'; - attrArray[3]='i'; - *( (int32*) (attrArray+4))=attr.size(); - memcpy(attrArray+4+sizeof(int32),attr.data(),sizeof(int32)*attr.size());//copy array data - return 4+sizeof(int32)+sizeof(int32)*attr.size(); -}; - -int bamAttrArrayWriteSAMtags(string &attrStr, char *attrArray) {//write bam record into attrArray for string attribute attString - size_t pos1=0, pos2=0; - int nattr=0; - do {//cycle over multiple tags separated by tab - pos2 = attrStr.find('\t',pos1); - string attr1 = attrStr.substr(pos1, pos2-pos1); - pos1=pos2+1; - - if (attr1.empty()) - continue; //extra tab at the beginning, or consecutive tabs - - switch (attr1.at(3)) { - case 'i': - { - int32 a1=stol(attr1.substr(5)); - nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); - break; - }; - case 'A': - { - char a1=attr1.at(5); - nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); - break; - }; - break; - case 'Z': - { - string a1=attr1.substr(5); - nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); - break; - }; - case 'f': - { - float a1=stof(attr1.substr(5)); - nattr += bamAttrArrayWrite(a1,attr1.c_str(),attrArray+nattr); - break; - }; - }; - } while (pos2!= string::npos); - - return nattr; -}; - -template -int bamAttrArrayWriteInt(intType xIn, const char* tagName, char* attrArray, Parameters &P) {//adapted from samtools - attrArray[0]=tagName[0];attrArray[1]=tagName[1]; - #define ATTR_RECORD_INT(_intChar,_intType,_intValue) attrArray[2] = _intChar; *(_intType*)(attrArray+3) = (_intType) _intValue; return 3+sizeof(_intType) - int64 x = (int64) xIn; - if (x < 0) { - if (x >= -127) { - ATTR_RECORD_INT('c',int8_t,x); - } else if (x >= -32767) { - ATTR_RECORD_INT('s',int16_t,x); - } else { - ATTR_RECORD_INT('i',int32_t,x); - if (!(x>=-2147483647)) { - ostringstream errOut; - errOut <<"EXITING because of FATAL BUG: integer out of range for BAM conversion: "<< x <<"\n"; - errOut <<"SOLUTION: contact Alex Dobin at dobin@cshl.edu\n"; - exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); - }; - }; - } else { - if (x <= 255) { - ATTR_RECORD_INT('C',uint8_t,x); - } else if (x <= 65535) { - ATTR_RECORD_INT('S',uint16_t,x); - } else { - ATTR_RECORD_INT('I',uint32_t,x); - if (!(x<=4294967295)) { - ostringstream errOut; - errOut <<"EXITING because of FATAL BUG: integer out of range for BAM conversion: "<< x <<"\n"; - errOut <<"SOLUTION: contact Alex Dobin at dobin@cshl.edu\n"; - exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); - }; - }; - }; + //cout << nMM<<" "< outSAMattrOrder, char** outBAMarray, uint* outBAMarrayN) { +int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint trChrStart, uint mateChr, uint mateStart, char mateStrand, int alignType, bool *mateMap, vector outSAMattrOrder, char** outBAMarray, uint* outBAMarrayN) { //return: number of lines (mates) //alignType>=0: unmapped reads @@ -195,7 +67,7 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint uint16 samFLAG=0; - bool flagPaired = P.readNmates==2; + bool flagPaired = P.readNmates==2; //not readNends: this is about alignments uint nMates=1; if (alignType<0) {//mapped reads: SAM @@ -224,7 +96,16 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint calcCIGAR(trOut, nMates, iExMate, leftMate); }; - for (uint imate=0;imate < (alignType<0 ? nMates:P.readNmates);imate++) { + int32 gxgnGene = -1; //gene to output in GX/GN + if (P.outSAMattrPresent.GX || P.outSAMattrPresent.GN) { + auto annFeat = readAnnot.annotFeatures[P.pSolo.samAttrFeature]; + if (annFeat.fSet.size()==1 && iTrOut < annFeat.fAlign.size() && annFeat.fAlign[iTrOut].size()==1) { + // 2nd condition needed when this function is called to output transcriptomic alignments, where GX/GN are not allowed, and iTrOut can be large + gxgnGene = *annFeat.fAlign[iTrOut].begin(); + }; + }; + + for (uint imate=0;imate < (alignType<0 ? nMates:P.readNmates);imate++) { //not readNends: this is about alignments uint iEx1=0; uint iEx2=0; @@ -238,17 +119,17 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint uint trimL1=0, trimR1=0; if (alignType>=0) {//this mate is unmapped - if (mateMapped!=NULL && mateMapped[imate]) continue; //this mate was mapped, do not record it as unmapped + if (mateMap!=NULL && mateMap[imate]) continue; //this mate was mapped, do not record it as unmapped samFLAG=0x4; - if (P.readNmates==2) {//paired read + if (P.readNmates==2) {//paired read, //not readNends: this is about alignments samFLAG|=0x1 + (imate==0 ? 0x40 : 0x80); - if (mateMapped[1-imate]) {//mate mapped + if (mateMap[1-imate]) {//mate mapped if (trOut.Str!=(1-imate)) {//mate strand reverted samFLAG|=0x20; }; mateChr=trOut.Chr; - trChrStart=mapGen.chrStart[mateChr]; + trChrStart=genOut.chrStart[mateChr]; mateStart=trOut.exons[0][EX_G] - trChrStart; mateStrand= trOut.Str == (1-imate) ? 0 : 1; @@ -264,7 +145,7 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint if (readFilter=='Y') samFLAG|=0x200; //not passing quality control - if (mateMapped[1-imate]) + if (mateMap[1-imate]) {//mate is mapped, fill the infromation from trOut }; @@ -279,13 +160,34 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint attrN+=bamAttrArrayWriteInt(trOut.nMM,"nM",attrOutArray+attrN,P); attrN+=bamAttrArrayWrite((to_string((uint) alignType)).at(0), "uT",attrOutArray+attrN); //cast to uint is only necessary for old compilers - if (!P.outSAMattrRG.empty()) attrN+=bamAttrArrayWrite(P.outSAMattrRG.at(readFilesIndex),"RG",attrOutArray+attrN); - + if (P.outSAMattrPresent.RG) + attrN+=bamAttrArrayWrite(P.outSAMattrRG.at(readFilesIndex),"RG",attrOutArray+attrN); + if (P.outSAMattrPresent.CR) + attrN+=bamAttrArrayWrite(soloRead->readBar->cbSeq,"CR",attrOutArray+attrN); + if (P.outSAMattrPresent.CY) + attrN+=bamAttrArrayWrite(soloRead->readBar->cbQual,"CY",attrOutArray+attrN); + if (P.outSAMattrPresent.CB && soloRead->readBar->cbSeqCorrected!="") + attrN+=bamAttrArrayWrite(soloRead->readBar->cbSeqCorrected,"CB",attrOutArray+attrN); + if (P.outSAMattrPresent.UR) + attrN+=bamAttrArrayWrite(soloRead->readBar->umiSeq,"UR",attrOutArray+attrN); + if (P.outSAMattrPresent.UY) + attrN+=bamAttrArrayWrite(soloRead->readBar->umiQual,"UY",attrOutArray+attrN); + if (P.outSAMattrPresent.sM) + attrN+=bamAttrArrayWrite(soloRead->readBar->cbMatch,"sM",attrOutArray+attrN); + if (P.outSAMattrPresent.sS) + attrN+=bamAttrArrayWrite(soloRead->readBar->bSeq,"sS",attrOutArray+attrN); + if (P.outSAMattrPresent.sQ) + attrN+=bamAttrArrayWrite(soloRead->readBar->bQual,"sQ",attrOutArray+attrN); + if (P.outSAMattrPresent.cN) { + vector v1={(int32)clipMates[imate][0].clippedN, (int32)clipMates[imate][1].clippedN}; + attrN+=bamAttrArrayWrite(v1,"cN",attrOutArray+attrN); + }; + } else {//this mate is mapped if (flagPaired) {//paired reads samFLAG=0x0001; if (iExMate==trOut.nExons-1) {//single mate - if (mateChr>mapGen.nChrReal) samFLAG|=0x0008; //not mapped as pair + if (mateChr>genOut.nChrReal) samFLAG|=0x0008; //not mapped as pair } else {//properly paired samFLAG|=0x0002; //mapped as pair }; @@ -295,11 +197,8 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint if (readFilter=='Y') samFLAG|=0x200; //not passing quality control - if (alignType==-11 || alignType==-12 || alignType==-13) { - samFLAG|=0x800; //mark chimeric alignments - } else {//only non-chimeric alignments will be marked as non-primary, since chimeric are already marked with 0x800 - if (!trOut.primaryFlag) samFLAG|=0x100;//mark not primary align - }; + if (alignType==-11 || alignType==-12 || alignType==-13) samFLAG|=0x800; //mark chimeric alignments + if (!trOut.primaryFlag) samFLAG|=0x100; //mark not primary align iEx1 = (imate==0 ? 0 : iExMate+1); iEx2 = (imate==0 ? iExMate : trOut.nExons-1); @@ -322,13 +221,13 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint uint trimL; if (Str==0 && Mate==0) { - trimL=clip5pNtotal[Mate]; + trimL=clipMates[Mate][0].clippedN; } else if (Str==0 && Mate==1) { - trimL=clip3pNtotal[Mate]; + trimL=clipMates[Mate][1].clippedN; } else if (Str==1 && Mate==0) { - trimL=clip3pNtotal[Mate]; + trimL=clipMates[Mate][1].clippedN; } else { - trimL=clip5pNtotal[Mate]; + trimL=clipMates[Mate][0].clippedN; }; nCIGAR=0; //number of CIGAR operations @@ -347,20 +246,19 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint uint gapR=trOut.exons[ii][EX_R]-trOut.exons[ii-1][EX_R]-trOut.exons[ii-1][EX_L]; //it's possible to have a D or N and I at the same time if (gapR>0){ - packedCIGAR[nCIGAR++]=gapR<=0 || trOut.sjAnnot[ii-1]==1) {//junction: N - packedCIGAR[nCIGAR++]=gapG<0) {//deletion: N + } else if (gapG>0) {//deletion: D packedCIGAR[nCIGAR++]=gapG<0) //do not record 0-length blocks (which could appear near junctions followed by deletions) + packedCIGAR[nCIGAR++]=trOut.exons[ii][EX_L]< v1={(int32)clipMates[imate][0].clippedN, (int32)clipMates[imate][1].clippedN}; + attrN+=bamAttrArrayWrite(v1,"cN",attrOutArray+attrN); + break; + }; case ATTR_NM: if ( tagNM == (uint) -1 ) samAttrNM_MD (trOut, iEx1, iEx2, tagNM, tagMD); attrN+=bamAttrArrayWriteInt(tagNM,"NM",attrOutArray+attrN,P); @@ -433,8 +338,8 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint for (uint ii=iEx1;ii<=iEx2;ii++) { rb.push_back( (int32) trOut.exons[ii][EX_R]+1 ); rb.push_back( (int32) trOut.exons[ii][EX_R]+trOut.exons[ii][EX_L]); - rb.push_back( (int32) (trOut.exons[ii][EX_G]-mapGen.chrStart[trOut.Chr]+1) ); - rb.push_back( (int32) (trOut.exons[ii][EX_G]-mapGen.chrStart[trOut.Chr]+trOut.exons[ii][EX_L]) ); + rb.push_back( (int32) (trOut.exons[ii][EX_G]-genOut.chrStart[trOut.Chr]+1) ); + rb.push_back( (int32) (trOut.exons[ii][EX_G]-genOut.chrStart[trOut.Chr]+trOut.exons[ii][EX_L]) ); }; attrN+=bamAttrArrayWrite(rb,"rB",attrOutArray+attrN); }; @@ -472,33 +377,91 @@ int ReadAlign::alignBAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint attrN+=bamAttrArrayWrite(matesCIGAR[1-imate],"MC",attrOutArray+attrN); }; break; - + + //solo case ATTR_CR: - attrN+=bamAttrArrayWrite(soloRead->readBar->cbSeq,"CR",attrOutArray+attrN); + attrN+=bamAttrArrayWrite(soloRead->readBar->cbSeq,"CR",attrOutArray+attrN); break; case ATTR_CY: - attrN+=bamAttrArrayWrite(soloRead->readBar->cbQual,"CY",attrOutArray+attrN); + attrN+=bamAttrArrayWrite(soloRead->readBar->cbQual,"CY",attrOutArray+attrN); break; case ATTR_UR: - attrN+=bamAttrArrayWrite(soloRead->readBar->umiSeq,"UR",attrOutArray+attrN); + attrN+=bamAttrArrayWrite(soloRead->readBar->umiSeq,"UR",attrOutArray+attrN); break; case ATTR_UY: - attrN+=bamAttrArrayWrite(soloRead->readBar->umiQual,"UY",attrOutArray+attrN); + attrN+=bamAttrArrayWrite(soloRead->readBar->umiQual,"UY",attrOutArray+attrN); break; + case ATTR_GX: + { + string algenes = gxgnGene<0 ? "-" : chunkTr->geID[gxgnGene]; + attrN+=bamAttrArrayWrite(algenes, "GX",attrOutArray+attrN); + }; + break; + + case ATTR_GN: + { + string algenes = gxgnGene<0 ? "-" : chunkTr->geName[gxgnGene]; + attrN+=bamAttrArrayWrite(algenes, "GN",attrOutArray+attrN); + }; + break; + + case ATTR_gx: + { + string algenes; + for (auto &gg: readAnnot.annotFeatures[P.pSolo.samAttrFeature].fAlign[iTrOut]) + algenes += chunkTr->geID[gg] + ";"; + if (algenes.size()>0) { + algenes.pop_back(); + } else { + algenes = "-"; + }; + attrN+=bamAttrArrayWrite(algenes,"gx",attrOutArray+attrN); + }; + break; + + case ATTR_gn: + { + string algenes; + for (auto &gg: readAnnot.annotFeatures[P.pSolo.samAttrFeature].fAlign[iTrOut]) + algenes += chunkTr->geName[gg] + ";"; + if (algenes.size()>0) { + algenes.pop_back(); + } else { + algenes = "-"; + }; + attrN+=bamAttrArrayWrite(algenes,"gn",attrOutArray+attrN); + }; + break; + + case ATTR_sM: + attrN+=bamAttrArrayWrite(soloRead->readBar->cbMatch,"sM",attrOutArray+attrN); + break; + case ATTR_sS: + attrN+=bamAttrArrayWrite(soloRead->readBar->bSeq,"sS",attrOutArray+attrN); + break; + case ATTR_sQ: + attrN+=bamAttrArrayWrite(soloRead->readBar->bQual,"sQ",attrOutArray+attrN); + break; + + case ATTR_CB: + if (soloRead->readBar->cbSeqCorrected!="") //only if corrected CB is defined (e.g. CB_samTagOut), otherwise it will be added at the BAM sorting stage + attrN+=bamAttrArrayWrite(soloRead->readBar->cbSeqCorrected,"CB",attrOutArray+attrN); + break; + case ATTR_UB: //will be added at the BAM sorting stage + break; + default: ostringstream errOut; errOut <<"EXITING because of FATAL BUG: unknown/unimplemented SAM/BAM atrribute (tag): "<logMain, EXIT_CODE_PARAMETER, P); }; }; }; - if (P.readFilesTypeN==10) { -// if (readNameExtra[Mate].size()<1) -// cout << iReadAll <<" " <1) { pBAM[6]=trOut.Chr; - } else if (mateChr1) { pBAM[7]=trOut.exons[(imate==0 ? iExMate+1 : 0)][EX_G] - trChrStart; - } else if (mateChr @@ -46,7 +46,7 @@ void ReadAlign::chimericDetection() { chimRecord=chimericDetectionOld(); chimericDetectionOldOutput(); } else if (trBest->maxScore <= (int) (readLength[0]+readLength[1]) - (int) P.pCh.nonchimScoreDropMin) {//require big enough drop in the best score - chimRecord=chimDet->chimericDetectionMult(nW, readLength, trBest->maxScore, false); + chimRecord=chimDet->chimericDetectionMult(nW, readLength, trBest->maxScore, NULL); }; if ( chimRecord ) { diff --git a/source/ReadAlign_chimericDetectionOldOutput.cpp b/source/ReadAlign_chimericDetectionOldOutput.cpp index b4569d3f..68416561 100644 --- a/source/ReadAlign_chimericDetectionOldOutput.cpp +++ b/source/ReadAlign_chimericDetectionOldOutput.cpp @@ -1,5 +1,6 @@ #include "ReadAlign.h" #include "BAMfunctions.h" +#include "ChimericAlign.h" void ReadAlign::chimericDetectionOldOutput() { @@ -7,113 +8,34 @@ void ReadAlign::chimericDetectionOldOutput() { return; }; - chimN=2; //this is hard-coded for now //re-calculate the score for chimeric transcripts trChim[0].alignScore(Read1, mapGen.G, P); trChim[1].alignScore(Read1, mapGen.G, P); - int chimRepresent=-999, chimType=0; - if (trChim[0].exons[0][EX_iFrag]!=trChim[0].exons[trChim[0].nExons-1][EX_iFrag]) {//tr0 has both mates - chimRepresent = 0; - chimType = 1; - trChim[0].primaryFlag=true;//paired portion is primary - trChim[1].primaryFlag=false; - } else if (trChim[1].exons[0][EX_iFrag]!=trChim[1].exons[trChim[1].nExons-1][EX_iFrag]) {//tr1 has both mates - chimRepresent = 1; - chimType = 1; - trChim[1].primaryFlag=true;//paired portion is primary - trChim[0].primaryFlag=false; - } else if (trChim[0].exons[0][EX_iFrag]!=trChim[1].exons[0][EX_iFrag]) {//tr0 and tr1 are single different mates - chimRepresent = -1; - chimType = 2; - trChim[0].primaryFlag=true; - trChim[1].primaryFlag=true; - } else {//two chimeric segments are on the same mate - this can only happen for single-end reads - chimRepresent = (trChim[0].maxScore > trChim[1].maxScore) ? 0 : 1; - chimType = 3; - trChim[chimRepresent].primaryFlag=true; - trChim[1-chimRepresent].primaryFlag=false; - }; - - if (P.pCh.out.bam) {//BAM output - int alignType, bamN=0, bamIsuppl=-1, bamIrepr=-1; - uint bamBytesTotal=0;//estimate of the total size of all bam records, for output buffering - uint mateChr,mateStart; - uint8_t mateStrand; - for (uint itr=0;itr=0) { - bam1_t *b; - b=bam_init1(); - bam_read1_fromArray(outBAMoneAlign[tagI], b); - uint8_t* auxp=bam_aux_get(b,"NM"); - uint32_t auxv=bam_aux2i(auxp); - string tagSA1="SAZ"+mapGen.chrName[b->core.tid]+','+to_string((uint)b->core.pos+1) +',' + ( (b->core.flag&0x10)==0 ? '+':'-') + \ - ',' + bam_cigarString(b) + ',' + to_string((uint)b->core.qual) + ',' + to_string((uint)auxv) + ';' ; - - memcpy( (void*) (outBAMoneAlign[ii]+outBAMoneAlignNbytes[ii]), tagSA1.c_str(), tagSA1.size()+1);//copy string including \0 at the end - outBAMoneAlignNbytes[ii]+=tagSA1.size()+1; - * ( (uint32*) outBAMoneAlign[ii] ) = outBAMoneAlignNbytes[ii]-sizeof(uint32); - }; + if (P.pCh.out.samOld) { - if (P.outBAMunsorted) outBAMunsorted->unsortedOneAlign(outBAMoneAlign[ii], outBAMoneAlignNbytes[ii], ii>0 ? 0 : bamBytesTotal); - if (P.outBAMcoord) outBAMcoord->coordOneAlign(outBAMoneAlign[ii], outBAMoneAlignNbytes[ii], (iReadAll<<32) ); + chimN=2; //this is hard-coded for now + if (trChim[0].exons[0][EX_iFrag]!=trChim[0].exons[trChim[0].nExons-1][EX_iFrag]) {//tr0 has both mates + trChim[0].primaryFlag=true;//paired portion is primary + trChim[1].primaryFlag=false; + } else if (trChim[1].exons[0][EX_iFrag]!=trChim[1].exons[trChim[1].nExons-1][EX_iFrag]) {//tr1 has both mates + trChim[1].primaryFlag=true;//paired portion is primary + trChim[0].primaryFlag=false; + } else if (trChim[0].exons[0][EX_iFrag]!=trChim[1].exons[0][EX_iFrag]) {//tr0 and tr1 are single different mates + trChim[0].primaryFlag=true; + trChim[1].primaryFlag=true; + } else {//two chimeric segments are on the same mate - this can only happen for single-end reads + int chimRepresent = (trChim[0].maxScore > trChim[1].maxScore) ? 0 : 1; + trChim[chimRepresent].primaryFlag=true; + trChim[1-chimRepresent].primaryFlag=false; }; - }; - if (P.pCh.out.samOld) { for (uint iTr=0;iTrtrChim[ii-1].exons[0][EX_G])) { - segLmin=segLen[ii][jj]; - i1=ii;//trChim of the shortest segment length - i2=jj;//mate of the shortest segment length - }; - }; - }; - - if (i2==1) {//eliminate mate1: simply cut the exons that belong to mate1 - trChim[i1].nExons=segEx[i1]+1; - } else {//eliminate mate 0: shift mate1 exon to the beginning - for (uint iex=0; iexmaxScore <= (int) (readLength[0]+readLength[1]) - (int) P.pCh.nonchimScoreDropMin) {//require big enough drop in the best score // new chimeric detection routine - chimRecord=seRA.chimDet->chimericDetectionMult(seRA.nW, seRA.readLength, seRA.trBest->maxScore, true); + chimRecord=seRA.chimDet->chimericDetectionMult(seRA.nW, seRA.readLength, seRA.trBest->maxScore, this); }; if ( chimRecord ) { diff --git a/source/ReadAlign_mapOneRead.cpp b/source/ReadAlign_mapOneRead.cpp index 72c61e44..1fd7eada 100644 --- a/source/ReadAlign_mapOneRead.cpp +++ b/source/ReadAlign_mapOneRead.cpp @@ -14,7 +14,7 @@ int ReadAlign::mapOneRead() { revertStrand = false; //the 2nd read is awlays on opposite strand. 1st and 2nd reads have already been reversed. if (Lread>0) { - Nsplit=qualitySplit(Read1[0], Qual1[0], Lread, P.Qsplit, P.maxNsplit, P.minLsplit, splitR); + Nsplit=qualitySplit(Read1[0], Lread, P.maxNsplit, P.seedSplitMin, splitR); // splitR[0][fragnum] => good region start position (from SequenceFuns.cpp) // splitR[1][fragnum] => good reagion length // splitR[2][fragnum] => fragnum ? @@ -33,7 +33,7 @@ int ReadAlign::mapOneRead() { trInit->readLengthOriginal=readLengthOriginal; trInit->readLengthPairOriginal=readLengthPairOriginal; trInit->readLength=readLength; - trInit->readNmates=readNmates; + trInit->readNmates=readNmates; //not readNends: this is alignment trInit->readName=readName; trBest=trInit; @@ -62,7 +62,7 @@ int ReadAlign::mapOneRead() { Lmapped=0; // length of segment mapped so far. // begin mapping starting from segment start position (istart*Lstart) - while ( istart*Lstart + Lmapped + P.minLmap < splitR[1][ip] ) {//map until unmapped portion is <=minLmap (default: 5) + while ( istart*Lstart + Lmapped + P.seedMapMin < splitR[1][ip] ) {//map until unmapped portion is <=minLmap (default: 5) // Shift is the position in the read to begin mapping from. uint Shift = iDir==0 ? ( splitR[0][ip] + istart*Lstart + Lmapped ) : \ diff --git a/source/ReadAlign_mapOneReadSpliceGraph.cpp b/source/ReadAlign_mapOneReadSpliceGraph.cpp new file mode 100755 index 00000000..7bcab339 --- /dev/null +++ b/source/ReadAlign_mapOneReadSpliceGraph.cpp @@ -0,0 +1,40 @@ +#include "ReadAlign.h" +#include "SequenceFuns.h" +#include "Stats.h" +#include "serviceFuns.cpp" + +void ReadAlign::mapOneReadSpliceGraph() +{ + #ifdef OFF_BEFORE_SEEDING + #warning OFF_BEFORE_SEEDING + nW=0; + return; + #endif + + if (LreadrLength=0; //min good piece length + nW=0; + return; + }; + + resetN(); //reset aligns counters to 0 + + //reset/initialize a transcript + trInit->reset(); + trInit->Chr=0; trInit->Str=0; trInit->roStr=0; trInit->cStart=0; trInit->gLength=0; //to generate nice output of 0 for non-mapped reads + trInit->iRead=iRead; + trInit->Lread=Lread; + trInit->nExons=0; + trInit->readLengthOriginal=readLengthOriginal; + trInit->readLengthPairOriginal=readLengthPairOriginal; + trInit->readLength=readLength; + trInit->readNmates=readNmates; //not readNends: this is alignment + trInit->readName=readName; + + trBest=trInit; + + splGraph->findSuperTr(Read1[0], Read1[2], Lread, readName, mapGen); + + return; +}; diff --git a/source/ReadAlign_maxMappableLength2strands.cpp b/source/ReadAlign_maxMappableLength2strands.cpp index ff5653fc..cdfd0b79 100644 --- a/source/ReadAlign_maxMappableLength2strands.cpp +++ b/source/ReadAlign_maxMappableLength2strands.cpp @@ -38,7 +38,7 @@ uint ReadAlign::maxMappableLength2strands(uint pieceStartIn, uint pieceLengthIn, //find SA boundaries uint Lind=Lmax; - while (Lind>0) {//check the precense of the prefix for Lind + while (Lind>0) {//check the presence of the prefix for Lind iSA1=mapGen.SAi[mapGen.genomeSAindexStart[Lind-1]+ind1]; // starting point for suffix array search. if ((iSA1 & mapGen.SAiMarkAbsentMaskC) == 0) {//prefix exists break; @@ -48,14 +48,21 @@ uint ReadAlign::maxMappableLength2strands(uint pieceStartIn, uint pieceLengthIn, }; }; - // define lower bound for suffix array range search. + // define upper bound for suffix array range search. + bool iSA2good = true; if (mapGen.genomeSAindexStart[Lind-1]+ind1+1 < mapGen.genomeSAindexStart[Lind]) {//we are not at the end of the SA - iSA2=((mapGen.SAi[mapGen.genomeSAindexStart[Lind-1]+ind1+1] & mapGen.SAiMarkNmask) & mapGen.SAiMarkAbsentMask) - 1; + iSA2 = mapGen.SAi[mapGen.genomeSAindexStart[Lind-1]+ind1+1]; + if ( (iSA2 & mapGen.SAiMarkAbsentMaskC) == 0) { + iSA2 = (iSA2 & mapGen.SAiMarkNmask) - 1; + } else { + iSA2 = mapGen.nSA-1; //safe, but can probably do better + iSA2good = false; + }; } else { iSA2=mapGen.nSA-1; + iSA2good = false; }; - //#define SA_SEARCH_FULL #ifdef SA_SEARCH_FULL @@ -63,13 +70,14 @@ uint ReadAlign::maxMappableLength2strands(uint pieceStartIn, uint pieceLengthIn, maxL=0; Nrep = maxMappableLength(mapGen, Read1, pieceStart, pieceLength, iSA1 & mapGen.SAiMarkNmask, iSA2, dirR, maxL, indStartEnd); #else - if (Lind < P.pGe.gSAindexNbases && (iSA1 & mapGen.SAiMarkNmaskC)==0 ) {//no need for SA search + bool iSA1noN = (iSA1 & mapGen.SAiMarkNmaskC)==0; + if (Lind < P.pGe.gSAindexNbases && iSA1noN && iSA2good) {//no need for SA search // very short seq, already found hits in suffix array w/o having to search the genome for extensions. indStartEnd[0]=iSA1; indStartEnd[1]=iSA2; Nrep=indStartEnd[1]-indStartEnd[0]+1; maxL=Lind; - } else if (iSA1==iSA2) {//unique align already, just find maxL + } else if (iSA1==iSA2 && iSA1noN && iSA2good) {//unique align already, just find maxL if ((iSA1 & mapGen.SAiMarkNmaskC)!=0) { ostringstream errOut; errOut << "BUG: in ReadAlign::maxMappableLength2strands"; @@ -79,12 +87,12 @@ uint ReadAlign::maxMappableLength2strands(uint pieceStartIn, uint pieceLengthIn, Nrep=1; bool comparRes; maxL=compareSeqToGenome(mapGen, Read1, pieceStart, pieceLength, Lind, iSA1, dirR, comparRes); - } else {//SA search, pieceLength>maxL - if ( (iSA1 & mapGen.SAiMarkNmaskC)==0 ) {//no N in the prefix - maxL=Lind; + } else {//need SA search, pieceLength>maxL + if (iSA2good && iSA1noN) { + maxL = Lind; //Lind bases were already matched } else { maxL=0; - }; + }; Nrep = maxMappableLength(mapGen, Read1, pieceStart, pieceLength, iSA1 & mapGen.SAiMarkNmask, iSA2, dirR, maxL, indStartEnd); }; #endif diff --git a/source/ReadAlign_multMapSelect.cpp b/source/ReadAlign_multMapSelect.cpp index 94fffa56..a23e07e7 100644 --- a/source/ReadAlign_multMapSelect.cpp +++ b/source/ReadAlign_multMapSelect.cpp @@ -38,91 +38,57 @@ void ReadAlign::multMapSelect() {//select multiple mappers from all transcripts trMult[nTr]->Str = trAll[iW][0]->Str; trMult[nTr]->roStr = trAll[iW][0]->roStr; - if ( (trAll[iW][iTr]->maxScore + P.outFilterMultimapScoreRange) >= maxScore) nTrMate++; - nTr++; }; }; }; - if (nTr > P.outFilterMultimapNmax || nTr==0) - {//too multi OR no alignments, no need for further processing, since it will be considered unmapped + if (nTr > P.outFilterMultimapNmax || nTr==0){ + //too multi OR no alignments, no need for further processing, since it will be considered unmapped return; }; - for (uint iTr=0; iTrroStart = trMult[iTr]->roStr==0 ? trMult[iTr]->rStart : Lread - trMult[iTr]->rStart - trMult[iTr]->rLength; trMult[iTr]->cStart=trMult[iTr]->gStart - mapGen.chrStart[trMult[iTr]->Chr]; }; -// if (P.outMultimapperOrder.sortCoord) -// {//sort multimappers by coordinate -// uint *s=new uint[nTr*2]; -// Transcript **t=new Transcript*[nTr]; -// for (uint itr=0; itrexons[0][EX_G]; -// s[itr*2+1]=itr; -// t[itr]=trMult[itr]; -// }; -// qsort((void*) s, nTr, sizeof(uint)*2, funCompareUint1); -// for (uint itr=0; itrprimaryFlag=true; - } else - {//multimappers + } else {//multimappers int nbest=0; - if (P.outMultimapperOrder.random || P.outSAMmultNmax != (uint) -1 ) - {//bring the best alignment to the top of the list. TODO sort alignments by the score? - for (uint itr=0; itrmaxScore == maxScore ) - { + if (P.outMultimapperOrder.random || P.outSAMmultNmax != (uint) -1 ) {//bring the best alignment to the top of the list. TODO sort alignments by the score? + for (uint itr=0; itrmaxScore == maxScore ) { swap(trMult[itr],trMult[nbest]); ++nbest; }; }; }; - if (P.outMultimapperOrder.random) - {//shuffle separately the best aligns, and the rest - for (int itr=nbest-1; itr>=1; itr--) - {//Fisher-Yates-Durstenfeld-Knuth shuffle + + if (P.outMultimapperOrder.random) {//shuffle separately the best aligns, and the rest + for (int itr=nbest-1; itr>=1; itr--) {//Fisher-Yates-Durstenfeld-Knuth shuffle int rand1=int (rngUniformReal0to1(rngMultOrder)*itr+0.5); swap(trMult[itr],trMult[rand1]); }; - for (int itr=nTr-nbest-1; itr>=1; itr--) - {//Fisher-Yates-Durstenfeld-Knuth shuffle + for (int itr=nTr-nbest-1; itr>=1; itr--) {//Fisher-Yates-Durstenfeld-Knuth shuffle int rand1=int (rngUniformReal0to1(rngMultOrder)*itr+0.5); swap(trMult[nbest+itr],trMult[nbest+rand1]); }; }; - if ( P.outSAMprimaryFlag=="AllBestScore" ) - { + if ( P.outSAMprimaryFlag=="AllBestScore" ) { for (uint itr=0; itrmaxScore == maxScore ) trMult[itr]->primaryFlag=true; }; - } else if (P.outMultimapperOrder.random || P.outSAMmultNmax != (uint) -1) - { + } else if (P.outMultimapperOrder.random || P.outSAMmultNmax != (uint) -1) { trMult[0]->primaryFlag=true;//mark as primary the first one in the random ordered list: best scoring aligns are already in front of the list - // for (uint itr=0; itrmaxScore == maxScore ) trMult[itr]->primaryFlag=true; - // break; - // }; - } else - {//old way + } else {//old way trBest->primaryFlag=true; }; }; + + //TODO re-point trBest to the primary one. This should not make a difference in the output }; diff --git a/source/ReadAlign_oneRead.cpp b/source/ReadAlign_oneRead.cpp old mode 100644 new mode 100755 index cdd5de20..92d644ef --- a/source/ReadAlign_oneRead.cpp +++ b/source/ReadAlign_oneRead.cpp @@ -1,28 +1,38 @@ #include "ReadAlign.h" #include "readLoad.h" +#include "readBarcodeLoad.h" #include "SequenceFuns.h" #include "ErrorWarning.h" +#include "GlobalVariables.h" int ReadAlign::oneRead() {//process one read: load, map, write //load read name, sequence, quality from the streams into internal arrays - int readStatus[2]; + int readStatus[P.readNends]; - - readStatus[0]=readLoad(*(readInStream[0]), P, 0, readLength[0], readLengthOriginal[0], readNameMates[0], Read0[0], Read1[0], Qual0[0], Qual1[0], clip3pNtotal[0], clip5pNtotal[0], clip3pAdapterN[0], iReadAll, readFilesIndex, readFilter, readNameExtra[0]); - if (P.readNmates==2) {//read the 2nd mate - readStatus[1]=readLoad(*(readInStream[1]), P, 1, readLength[1], readLengthOriginal[1], readNameMates[1], Read0[1], Read1[0]+readLength[0]+1, Qual0[1], Qual1[0]+readLength[0]+1, clip3pNtotal[1], clip5pNtotal[1], clip3pAdapterN[1], iReadAll, readFilesIndex, readFilter, readNameExtra[1]); - - if (readStatus[0]!=readStatus[1]) { + for (uint32 im=0; imlogMain, EXIT_CODE_INPUT_FILES, P); - } else if (readStatus[0]==-1) {//finished with the stream - return -1; }; + }; - //combine two reads together + if (readStatus[0]==-1) {//finished with the stream + return -1; + }; + + if (P.outFilterBySJoutStage != 2) { + for (uint32 im=0; imDEF_readSeqLengthMax) { @@ -33,12 +43,13 @@ int ReadAlign::oneRead() {//process one read: load, map, write exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); }; - Read1[0][readLength[0]]=MARK_FRAG_SPACER_BASE; //marker for spacer base - Qual1[0][readLength[0]]=0; - complementSeqNumbers(Read1[0]+readLength[0]+1,Read1[0]+readLength[0]+1,readLength[1]); //returns complement of Reads[ii] + //marker for spacer base + Read1[0][readLength[0]]=MARK_FRAG_SPACER_BASE; + + //copy 2nd mate into Read1[0] & reverse-complement + complementSeqNumbers(Read1[1],Read1[0]+readLength[0]+1,readLength[1]);//complement. Here Read1[1] is still the 2nd mate's numeric-sequence. Later Read1[1] will be reverse complement of the combined read. for (uint ii=0;ii readGeneFull={},readGene={}; - vector readTranscripts={}; - vector readGeneExon={}; - - outFilterPassed=true;//only false if the alignment is held for outFilterBySJoutStage - if (unmapType==-1) {//output transcripts - if (P.outFilterBySJoutStage==1) {//filtering by SJout - for (uint iTr=0;iTrnExons-1;iex++) {//check all junctions - if (trMult[iTr]->canonSJ[iex]>=0 && trMult[iTr]->sjAnnot[iex]==0) { - outFilterPassed=false; - break; - }; - }; - if (!outFilterPassed) break; - }; - if (!outFilterPassed) {//this read is held for further filtering BySJout, record fastq - unmapType=-3; //the read is not conisddred unmapped - statsRA.readN--; - statsRA.readBases -= readLength[0]+readLength[1]; - - for (uint im=0;imN; - for (uint iTr=0;iTrChrChr>=mapGen.genomeInsertChrIndFirst) { - trMult[nTrOut]=trMult[itr]; - trMult[nTrOut]->primaryFlag=false; - ++nTrOut; - }; - }; - if (nTrOut==0) { - outSAMfilterYes=false; - } else { - trMult[0]->primaryFlag=true; - }; - }; - }; + ReadAlign::outFilterBySJout();//sets outFilterBySJoutPass=false if read is held for the 2nd stage of outFilterBySJout + + if (outFilterBySJoutPass) {//otherwise align is held for the 2nd stage of outFilterBySJout + //////////////////////////////////// + if (unmapType<0) {//passed mappedFilter. Unmapped reads can have nTr>0 if (nTr>1) {//multimappers statsRA.mappedReadsM++; - unmapType=-1; + unmapType = -2; //not sure if this used } else if (nTr==1) {//unique mappers statsRA.mappedReadsU++; statsRA.transcriptStats(*(trMult[0]),Lread); - unmapType=-2; - } else {//cannot be - ostringstream errOut; - errOut << "EXITING because of a BUG: nTr=0 in outputAlignments.cpp"; - exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_BUG, P); }; - nTrOut=min(P.outSAMmultNmax,nTrOut); //number of to write to SAM/BAM files - - soloRead->readBar->getCBandUMI(readNameExtra.at(0)); + if (!P.pGe.transform.outSAM) { + ReadAlign::recordSJ(nTr, trMult, chunkOutSJ); //this will set mateMapped + } else { + ReadAlign::recordSJ(alignsGenOut.alN, alignsGenOut.alMult, chunkOutSJ); + }; - //write to SAM/BAM - for (uint iTr=0;iTrexons[0][EX_iFrag]]=true; - mateMapped1[trMult[iTr]->exons[trMult[iTr]->nExons-1][EX_iFrag]]=true; - - if (P.outSAMbool && outSAMfilterYes) {//SAM output - outBAMbytes+=outputTranscriptSAM(*(trMult[iTr]), nTr, iTr, (uint) -1, (uint) -1, 0, -1, NULL, outSAMstream); - if (P.outSAMunmapped.keepPairs && P.readNmates>1 && ( !mateMapped1[0] || !mateMapped1[1] ) ) {//keep pairs && paired reads && one of the mates not mapped in this transcript - outBAMbytes+= outputTranscriptSAM(*(trMult[iTr]), 0, 0, (uint) -1, (uint) -1, 0, 4, mateMapped1, outSAMstream); - }; - }; + ReadAlign::alignedAnnotation(); + }; - if ((P.outBAMunsorted || P.outBAMcoord) && outSAMfilterYes) {//BAM output - alignBAM(*(trMult[iTr]), nTr, iTr, mapGen.chrStart[trMult[iTr]->Chr], (uint) -1, (uint) -1, 0, -1, NULL, P.outSAMattrOrder,outBAMoneAlign, outBAMoneAlignNbytes); + //the operations below are both for mapped and unmapped reads + soloRead->readBar->getCBandUMI(Read0, Qual0, readLengthOriginal, readNameExtra[0], readFilesIndex, readName); - if (P.outBAMunsorted) {//unsorted - for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (imate>0 || iTr>0) ? 0 : (outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1])*2*nTrOut); - }; - if (P.outSAMunmapped.keepPairs && P.readNmates>1 && ( !mateMapped1[0] || !mateMapped1[1] ) ) {//keep pairs && paired reads && one of the mates not mapped in this transcript - alignBAM(*trMult[iTr], 0, 0, mapGen.chrStart[trMult[iTr]->Chr], (uint) -1, (uint) -1, 0, 4, mateMapped1, P.outSAMattrOrder, outBAMoneAlign, outBAMoneAlignNbytes); - for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (imate>0 || iTr>0) ? 0 : (outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1])*2*nTrOut); - }; - }; - }; + //transcripts: need to be run after CB/UMI are obtained to output CR/UR tags + if ( P.quant.trSAM.yes && unmapType<0) {//Aligned.toTranscriptome output, only for mapped + quantTranscriptome(chunkTr, nTr, trMult, alignTrAll); + }; + + soloRead->record((unmapType<0 ? nTr : 0), trMult, iReadAll, readAnnot); //need to supply nTr=0 for unmapped reads - if (P.outBAMcoord) {//coordinate sorted - for (uint imate=0; imatecoordOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (iReadAll<<32) | (iTr<<8) | trMult[iTr]->exons[0][EX_iFrag] ); - }; - }; + if (!P.pGe.transform.outSAM) { + ReadAlign::writeSAM(nTr, trMult, trBest); //this will set mateMapped + } else { + ReadAlign::writeSAM(alignsGenOut.alN, alignsGenOut.alMult, alignsGenOut.alBest); + }; + }; + + if (unmapType>=0) {//unmapped reads + statsRA.unmappedAll++; //include unmapType==4, i.e. one-mate alignments of PE reads - which may have been set in writeSAM above + ReadAlign::outReadsUnmapped(); //uses mateMapped that was set in writeSAM above + }; +}; - }; - }; - mateMapped[trBest->exons[0][EX_iFrag]]=true; - mateMapped[trBest->exons[trBest->nExons-1][EX_iFrag]]=true; +/////////////////////////////////////////////////////////////////////////////////////////////////// +void ReadAlign::recordSJ(uint64 nTrO, Transcript **trO, OutSJ *cSJ) +{//junction output for mapped reads (i.e. passed BySJout filtering) + if (!P.outSJ.yes) + return; //no SJ output + + if ( P.outSJfilterReads=="All" || nTrO==1 ) { + uint64 sjReadStartN=cSJ->N; + for (uint64 iTr=0; iTr1 && !(mateMapped[0] && mateMapped[1]) ) { - unmapType=4; +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ReadAlign::outFilterBySJout() +{//filtering by SJout + outFilterBySJoutPass=true;//only false if the alignment is held for outFilterBySJoutStage. True even if unmapped + + if (unmapType>0 || P.outFilterBySJoutStage!=1) + return; //unmapped, or 2nd stage + + for (uint iTr=0;iTrnExons-1;iex++) {//check all junctions + if (trMult[iTr]->canonSJ[iex]>=0 && trMult[iTr]->sjAnnot[iex]==0) { + outFilterBySJoutPass=false; + break; }; + }; + if (!outFilterBySJoutPass) + break; + }; + + if (!outFilterBySJoutPass) {//this read is held for further filtering BySJout, record fastq + unmapType=-3; //the read is not conisdered mapped + statsRA.readN--; + statsRA.readBases -= readLength[0]+readLength[1]; - if (unmapType==4 && P.outSAMunmapped.yes) {//output unmapped end for single-end alignments - if (P.outSAMbool && !P.outSAMunmapped.keepPairs && outSAMfilterYes) { - outBAMbytes+= outputTranscriptSAM(*trBest, 0, 0, (uint) -1, (uint) -1, 0, unmapType, mateMapped, outSAMstream); - }; + for (uint im=0;imChr], (uint) -1, (uint) -1, 0, unmapType, mateMapped, P.outSAMattrOrder, outBAMoneAlign, outBAMoneAlignNbytes); - for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], imate>0 ? 0 : outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1]); - }; - if (P.outBAMcoord) {//KeepPairs option does not affect for sorted BAM since we do not want multiple entries for the same unmapped read - outBAMcoord->coordOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], iReadAll); - }; +//////////////////////////////////////////////////////////////////////////////////////////////// +void ReadAlign::writeSAM(uint64 nTrOutSAM, Transcript **trOutSAM, Transcript *trBestSAM) +{ + outBAMbytes=0; + mateMapped[0] = mateMapped[1] = false; //mateMapped = are mates present in any of the transcripts? + + if (unmapType < 0 && outFilterBySJoutPass) {//write to SAM/BAM + + ////////////////////////////////////////////////////////////////////////////////// + /////////////outSAMfilter + if (P.outSAMfilter.yes) { + if (P.outSAMfilter.KeepOnlyAddedReferences) { + for (uint itr=0;itrChrChr>=mapGen.genomeInsertChrIndFirst) { + trOutSAM[nTrOutSAM1]=trOutSAM[itr]; + trOutSAM[nTrOutSAM1]->primaryFlag=false; + ++nTrOutSAM1; }; }; + if (nTrOutSAM1==0) { + return;//no SAM output + } else { + trOutSAM[0]->primaryFlag=true; + }; + nTrOutSAM = nTrOutSAM1; }; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////// write SAM/BAM + auto nTrOutWrite=min(P.outSAMmultNmax,nTrOutSAM); //number of aligns to write to SAM/BAM files + + for (uint iTr=0;iTrexons[0][EX_iFrag]]=true; + mateMapped1[trOutSAM[iTr]->exons[trOutSAM[iTr]->nExons-1][EX_iFrag]]=true; - if (P.outSJfilterReads=="All" || nTr==1) { - uint sjReadStartN=chunkOutSJ->N; - for (uint iTr=0;iTr1 && ( !mateMapped1[0] || !mateMapped1[1] ) ) {//keep pairs && paired reads && one of the mates not mapped in this transcript //not readNends: this is alignment + outBAMbytes+= outputTranscriptSAM(*(trOutSAM[iTr]), 0, 0, (uint) -1, (uint) -1, 0, 4, mateMapped1, outSAMstream); }; }; - - //genes - if ( P.quant.geCount.yes ) { - chunkTr->geneCountsAddAlign(nTr, trMult, readGeneExon); - }; - if ( P.quant.geneFull.yes ) { - chunkTr->geneFullAlignOverlap(nTr, trMult, P.pSolo.strand, readGeneFull); - }; + if (P.outBAMunsorted || P.outBAMcoord) {//BAM output + alignBAM(*(trOutSAM[iTr]), nTrOutSAM, iTr, mapGen.chrStart[trOutSAM[iTr]->Chr], (uint) -1, (uint) -1, 0, -1, NULL, P.outSAMattrOrder,outBAMoneAlign, outBAMoneAlignNbytes); - //transcripts - if ( P.quant.trSAM.yes ) {//NOTE: the transcripts are changed by this function (soft-clipping extended), cannot be reused - quantTranscriptome(chunkTr, nTrOut, trMult, alignTrAll, readTranscripts, readGene); + if (P.outBAMunsorted) {//unsorted + for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (imate>0 || iTr>0) ? 0 : (outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1])*2*nTrOutWrite); + }; + if (P.outSAMunmapped.keepPairs && P.readNmates>1 && ( !mateMapped1[0] || !mateMapped1[1] ) ) {//keep pairs && paired reads && one of the mates not mapped in this transcript //not readNends: this is alignment + alignBAM(*trOutSAM[iTr], 0, 0, mapGen.chrStart[trOutSAM[iTr]->Chr], (uint) -1, (uint) -1, 0, 4, mateMapped1, P.outSAMattrOrder, outBAMoneAlign, outBAMoneAlignNbytes); + for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (imate>0 || iTr>0) ? 0 : (outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1])*2*nTrOutWrite); + }; + }; + }; + + if (P.outBAMcoord) {//coordinate sorted + for (uint imate=0; imatecoordOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (iReadAll<<32) | (iTr<<8) | trOutSAM[iTr]->exons[0][EX_iFrag] ); + }; + }; }; + }; - //solo - soloRead->record(nTr, readGene, readGeneFull, trMult[0]); + ///////////////////////////////////////////////////////////////////////////////////////////// + //////// write unmapped ends + //TODO it's better to check all transcripts in the loop above for presence of both mates + mateMapped[trBestSAM->exons[0][EX_iFrag]] = true; + mateMapped[trBestSAM->exons[trBestSAM->nExons-1][EX_iFrag]] = true; + + if (P.readNmates>1 && !(mateMapped[0] && mateMapped[1]) ) {//not readNends: this is alignment + unmapType=4; }; - }; - if (unmapType>=0) {//unmapped reads - statsRA.unmappedAll++; - soloRead->readBar->getCBandUMI(readNameExtra.at(0)); - soloRead->record(nTr, readGene, readGeneFull, trMult[0]); - }; + if (unmapType==4 && P.outSAMunmapped.within) {//output unmapped ends for single-end alignments of PE reads + if (P.outSAMbool && !P.outSAMunmapped.keepPairs ) { + outBAMbytes+= outputTranscriptSAM(*trBestSAM, 0, 0, (uint) -1, (uint) -1, 0, unmapType, mateMapped, outSAMstream); + }; - if ( P.outSAMunmapped.within && unmapType>=0 && unmapType<4 ) {//output unmapped within && unmapped read && both mates unmapped + if ( P.outBAMcoord || (P.outBAMunsorted && !P.outSAMunmapped.keepPairs) ) {//BAM output + alignBAM(*trBestSAM, 0, 0, mapGen.chrStart[trBestSAM->Chr], (uint) -1, (uint) -1, 0, unmapType, mateMapped, P.outSAMattrOrder, outBAMoneAlign, outBAMoneAlignNbytes); + for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], imate>0 ? 0 : outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1]); + }; + if (P.outBAMcoord) {//KeepPairs option does not affect for sorted BAM since we do not want multiple entries for the same unmapped read + outBAMcoord->coordOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], iReadAll<<32); + }; + }; + }; + }; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////write completely unmapped + } else if (unmapType>=0 && P.outSAMunmapped.within) {//output unmapped within && unmapped read && both mates unmapped if (P.outBAMcoord || P.outBAMunsorted || P.quant.trSAM.bamYes) {//BAM output - alignBAM(*trBest, 0, 0, mapGen.chrStart[trBest->Chr], (uint) -1, (uint) -1, 0, unmapType, mateMapped, P.outSAMattrOrder, outBAMoneAlign, outBAMoneAlignNbytes); - for (uint imate=0; imateChr], (uint) -1, (uint) -1, 0, unmapType, mateMapped, P.outSAMattrOrder, outBAMoneAlign, outBAMoneAlignNbytes); + for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], imate>0 ? 0 : outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1]); }; @@ -200,20 +229,24 @@ void ReadAlign::outputAlignments() { outBAMquant->unsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], imate>0 ? 0 : outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1]); }; if (P.outBAMcoord) { - outBAMcoord->coordOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], iReadAll); + outBAMcoord->coordOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], iReadAll<<32); }; }; }; if (P.outSAMbool) {//output SAM - outBAMbytes+= outputTranscriptSAM(*trBest, 0, 0, (uint) -1, (uint) -1, 0, unmapType, mateMapped, outSAMstream); + outBAMbytes+= outputTranscriptSAM(*trBestSAM, 0, 0, (uint) -1, (uint) -1, 0, unmapType, mateMapped, outSAMstream); }; - }; + }; +}; - if (unmapType>=0 && P.outReadsUnmapped=="Fastx" ){//output to fasta/q files - for (uint im=0;im1) + if (P.readNmates>1) //not readNends: this is alignment chunkOutUnmappedReadsStream[im] <<" "<< int(mateMapped[0]) << int(mateMapped[1]); chunkOutUnmappedReadsStream[im] <<"\n"; chunkOutUnmappedReadsStream[im] << Read0[im] <<"\n"; @@ -222,14 +255,52 @@ void ReadAlign::outputAlignments() { chunkOutUnmappedReadsStream[im] << Qual0[im] <<"\n"; }; }; - if (P.pSolo.type>0) {//need to output 2nd (barcode) read - chunkOutUnmappedReadsStream[1] << readNameMates[0] <<"\n"; - uint32 qualStart = readNameExtra[0].find(' '); - chunkOutUnmappedReadsStream[1] << readNameExtra[0].substr(0,qualStart) <<"\n+\n"; - chunkOutUnmappedReadsStream[1] << readNameExtra[0].substr(qualStart+1) <<"\n"; - }; }; }; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void ReadAlign::spliceGraphWriteSAM() +{//temporary: SAM output for SpliceGraph + outBAMbytes=0; + uint64 nTrOutSAM = nTr; + if (mapGen.genomeOut.convYes) {//convert to new genome + nTrOutSAM=0; + for (uint32 iTr=0; iTrconvertGenomeCigar(*mapGen.genomeOut.g, *alignsGenOut.alMult[nTrOutSAM])) { + ++nTrOutSAM; + trMult[nTrOutSAM-1] = alignsGenOut.alMult[nTrOutSAM-1]; //point to new transcsript + }; + }; + nTrOutSAM=nTrOutSAM; + }; + for (uint iTr=0; iTrgeneCountsAddAlign(nTr, trMult, readAnnot.geneExonOverlap); + }; + //solo-GeneFull + if ( P.quant.geneFull.yes ) { + chunkTr->geneFullAlignOverlap(nTr, trMult, P.pSolo.strand, readAnnot.annotFeatures[SoloFeatureTypes::GeneFull]); + }; + //solo-Gene + if ( P.quant.gene.yes ) { + chunkTr->classifyAlign(trMult, nTr, readAnnot); + }; + //solo-GeneFull_ExonOverIntron + if ( P.quant.geneFull_ExonOverIntron.yes ) { + chunkTr->geneFullAlignOverlap_ExonOverIntron(nTr, trMult, P.pSolo.strand, readAnnot.annotFeatures[SoloFeatureTypes::GeneFull_ExonOverIntron], readAnnot.annotFeatures[SoloFeatureTypes::Gene]); + }; + //solo-GeneFull_Ex50pAS + if ( P.quant.geneFull_Ex50pAS.yes ) { + chunkTr->alignExonOverlap(nTr, trMult, P.pSolo.strand, readAnnot.annotFeatures[SoloFeatureTypes::GeneFull_Ex50pAS]); + }; +}; \ No newline at end of file diff --git a/source/ReadAlign_outputSpliceGraphSAM.cpp b/source/ReadAlign_outputSpliceGraphSAM.cpp new file mode 100755 index 00000000..910c43a6 --- /dev/null +++ b/source/ReadAlign_outputSpliceGraphSAM.cpp @@ -0,0 +1,164 @@ +#include "ReadAlign.h" +#include "SequenceFuns.h" +#include "ErrorWarning.h" + +uint64 ReadAlign::outputSpliceGraphSAM(Transcript const &trOut, uint nTrOut, uint iTrOut, ostream *outStream) +{ + + uint64 outStreamPos0=(uint64)outStream->tellp(); + + uint16 samFLAG=0; + if (readFilter=='Y') + samFLAG |= 0x200; //not passing quality control + + if (unmapType>=0) {//unmapped reads: SAM + samFLAG |= 0x4; + + *outStream << readName+1 <<"\t"<< samFLAG <<"\t"<< '*' <<"\t"<< '0' <<"\t"<< '0' <<"\t"<< '*'; + //mate + *outStream <<"\t"<< '*' <<"\t"<< '0' <<"\t"<< '0' ; + + *outStream <<"\t"<< Read0[0] <<"\t"<< (readFileType==2 ? Qual0[0]:"*") \ + <<"\tNH:i:0" <<"\tHI:i:0" <<"\tAS:i:"<tellp()-outStreamPos0; + }; + + //mapped + if (!trOut.primaryFlag) + samFLAG |= 0x100; + if (trOut.Str==1) + samFLAG |= 0x10; + + string cigar; + const static char* cigarChars="MIDNS"; + for (auto &cc : trOut.cigar) { + cigar += to_string(cc[1]) + cigarChars[cc[0]]; + }; + + char seqRev[DEF_readSeqLengthMax+1], qualRev[DEF_readSeqLengthMax+1]; + char *seqOut=NULL, *qualOut=NULL; + + if ( trOut.Str==0 ) {//seq strand is correct + seqOut=Read0[0]; + qualOut=Qual0[0]; + } else { + revComplementNucleotides(Read0[0], seqRev, Lread); + for (uint ii=0;ii=5) { + MAPQ=0; + } else if (nTrOut>=3) { + MAPQ=1; + } else if (nTrOut==2) { + MAPQ=3; + }; + + *outStream << readName+1 <<"\t"<< ((samFLAG & P.outSAMflagAND) | P.outSAMflagOR) <<"\t"<< genOut.chrName[trOut.Chr] <<"\t"<< trOut.gStart + 1 - genOut.chrStart[trOut.Chr] + <<"\t"<< MAPQ <<"\t"<< cigar; + + *outStream <<"\t"<< "*" <<"\t"<< 0 <<"\t"<< 0; + + *outStream <<"\t"<< seqOut; + + if (readFileType==2 && P.outSAMmode != "NoQS") {//fastq + *outStream <<"\t"<< qualOut ; + } else { + *outStream <<"\t"<< "*"; + }; + + uint32 tagNM = trOut.nMM + trOut.lIns + trOut.lDel; + + for (uint ii=0;ii1) { +// *outStream<< "\tMC:Z:" <logMain, EXIT_CODE_PARAMETER, P); + }; + }; + + if (P.readFilesTypeN==10 && !readNameExtra[0].empty()) {//SAM files as input - output extra attributes + *outStream << "\t" << readNameExtra.at(0); + }; + + *outStream << "\n"; //done with one SAM line + + return (uint)outStream->tellp()-outStreamPos0; +}; diff --git a/source/ReadAlign_outputTranscriptSAM.cpp b/source/ReadAlign_outputTranscriptSAM.cpp old mode 100644 new mode 100755 index f21d5941..c947e1a0 --- a/source/ReadAlign_outputTranscriptSAM.cpp +++ b/source/ReadAlign_outputTranscriptSAM.cpp @@ -2,7 +2,7 @@ #include "SequenceFuns.h" #include "ErrorWarning.h" -uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint mateChr, uint mateStart, char mateStrand, int unmapType, bool *mateMapped, ostream *outStream) { +uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint iTrOut, uint mateChr, uint mateStart, char mateStrand, int unmapType, bool *mateMap, ostream *outStream) { if (P.outSAMmode=="None") return 0; //no SAM output @@ -10,38 +10,32 @@ uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint i if (unmapType>=0) {//unmapped reads: SAM - for (uint imate=0;imatetellp()-outStreamPos0; };//if (unmapType>=0 && outStream != NULL) //unmapped reads: SAM - bool flagPaired = P.readNmates==2; + bool flagPaired = P.readNmates==2; //not readNends: this is alignment string CIGAR; //for SAM output need to split mates @@ -80,7 +73,7 @@ uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint i samFlagCommon=0x0001; if (iExMate==trOut.nExons-1) {//single mate - if (mateChr>mapGen.nChrReal) samFlagCommon+=0x0008; //not mapped as pair + if (mateChr>genOut.nChrReal) samFlagCommon+=0x0008; //not mapped as pair } else {//paired align if (P.alignEndsProtrude.concordantPair || \ @@ -140,13 +133,13 @@ uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint i uint trimL; if (Str==0 && Mate==0) { - trimL=clip5pNtotal[Mate]; + trimL=clipMates[Mate][0].clippedN; } else if (Str==0 && Mate==1) { - trimL=clip3pNtotal[Mate]; + trimL=clipMates[Mate][1].clippedN; } else if (Str==1 && Mate==0) { - trimL=clip3pNtotal[Mate]; + trimL=clipMates[Mate][1].clippedN; } else { - trimL=clip5pNtotal[Mate]; + trimL=clipMates[Mate][0].clippedN; }; uint trimL1 = trimL + trOut.exons[iEx1][EX_R] - (trOut.exons[iEx1][EX_R]0) {//deletion: N samStreamCIGAR << gapG; samStreamCIGAR << "D"; @@ -223,14 +216,14 @@ uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint i MAPQ=3; }; - *outStream << readName+1 <<"\t"<< ((samFLAG & P.outSAMflagAND) | P.outSAMflagOR) <<"\t"<< mapGen.chrName[trOut.Chr] <<"\t"<< trOut.exons[iEx1][EX_G] + 1 - mapGen.chrStart[trOut.Chr] + *outStream << readName+1 <<"\t"<< ((samFLAG & P.outSAMflagAND) | P.outSAMflagOR) <<"\t"<< genOut.chrName[trOut.Chr] <<"\t"<< trOut.exons[iEx1][EX_G] + 1 - genOut.chrStart[trOut.Chr] <<"\t"<< MAPQ <<"\t"<< CIGAR; if (nMates>1) { - *outStream <<"\t"<< "=" <<"\t"<< trOut.exons[(imate==0 ? iExMate+1 : 0)][EX_G]+ 1 - mapGen.chrStart[trOut.Chr] + *outStream <<"\t"<< "=" <<"\t"<< trOut.exons[(imate==0 ? iExMate+1 : 0)][EX_G]+ 1 - genOut.chrStart[trOut.Chr] <<"\t"<< (imate==0? "":"-") << trOut.exons[trOut.nExons-1][EX_G]+trOut.exons[trOut.nExons-1][EX_L]-trOut.exons[0][EX_G]; - } else if (mateChr0 || (ii==0 && iex>0 && trOut.canonSJ[iex]==-1) ) { @@ -271,7 +264,7 @@ uint ReadAlign::outputTranscriptSAM(Transcript const &trOut, uint nTrOut, uint i tagNM+=trOut.exons[iex+1][EX_G]-(trOut.exons[iex][EX_G]+trOut.exons[iex][EX_L]); tagMD+=to_string(matchN) + "^"; for (uint ii=trOut.exons[iex][EX_G]+trOut.exons[iex][EX_L];iilogMain, EXIT_CODE_PARAMETER, P); }; diff --git a/source/ReadAlign_outputTranscriptSJ.cpp b/source/ReadAlign_outputTranscriptSJ.cpp index 05179e81..96aefe60 100644 --- a/source/ReadAlign_outputTranscriptSJ.cpp +++ b/source/ReadAlign_outputTranscriptSJ.cpp @@ -8,6 +8,8 @@ void ReadAlign::outputTranscriptSJ(Transcript const &trOut, uint nTrOut, OutSJ * // if (nTrOut>1) return; //junctions from multi-mappers are not recorded // if (P.outSAMmode=="None") return; //no SAM output + if (trOut.nExons==0) + return; for (uint iex=0;iex=0) {//only record junctions, not indels or mate gap diff --git a/source/ReadAlign_peOverlapMergeMap.cpp b/source/ReadAlign_peOverlapMergeMap.cpp index c1a117a4..52d281ef 100644 --- a/source/ReadAlign_peOverlapMergeMap.cpp +++ b/source/ReadAlign_peOverlapMergeMap.cpp @@ -3,7 +3,7 @@ void ReadAlign::peOverlapMergeMap() { - if (!P.peOverlap.yes || P.readNmates!=2 ) {//no peOverlap + if (!P.peOverlap.yes || P.readNmates!=2 ) {//no peOverlap //not readNends: this is alignment peOv.yes=false; return; }; @@ -122,26 +122,18 @@ void ReadAlign::peMergeMates() { readLength[1]=0; readLengthOriginal[0]=Lread; readLengthOriginal[1]=0; - readNmates=1; + readNmates=1; //not readNends: this is alignment //fill Read1[1,2] complementSeqNumbers(Read1[0],Read1[1],Lread); //returns complement of Reads[ii] for (uint ii=0;iiMAX_N_EXONS) {//cannot transform this alignment to PE, too many exons + maxScore=0; + nExons=0; + return; + }; }; canonSJ[nExons-1]=-3; //marks "junction" between mates sjAnnot[nExons-1]=0; @@ -268,28 +265,97 @@ void Transcript::peOverlapSEtoPE(uint* mateStart, Transcript &t) {//convert alig void ReadAlign::peOverlapSEtoPE(ReadAlign &seRA) {//ReAdAlign: convert SE to PE and copy - nW=seRA.nW; - memcpy((void*) nWinTr, (void*) seRA.nWinTr, nW*sizeof(*nWinTr)); + //nW=seRA.nW; + //memcpy((void*) nWinTr, (void*) seRA.nWinTr, nW*sizeof(*nWinTr)); uint trNtotal=0; intScore bestScore=-10*Lread; trBest=trArray;//just to initialize - to the 0th spot in the trArray - for (uint iW=0; iWpeOverlapSEtoPE(peOv.mateStart, *seRA.trAll[iW][iTr]); - trAll[iW][iTr]->alignScore(Read1,mapGen.G,P); - if (trAll[iW][iTr]->maxScore > trAll[iW][0]->maxScore) { - swap(trAll[iW][iTr],trAll[iW][0]); + + uint64 iW1=0; + for (uint iW=0; iWpeOverlapSEtoPE(peOv.mateStart, *seRA.trAll[iW][iTr]); + if (trAll[iW1][iTr1]->nExons==0) + continue; //conversion did not work + + trAll[iW1][iTr1]->alignScore(Read1,mapGen.G,P); + if (trAll[iW1][iTr1]->maxScore > trAll[iW1][0]->maxScore) { + swap(trAll[iW][iTr1],trAll[iW][0]); }; + + ++iTr1; + ++trNtotal; }; - if (trAll[iW][0]->maxScore>bestScore) { - trBest=trAll[iW][0]; - bestScore=trBest->maxScore; + if (iTr1>0) {//if conversion worked for at least one align + nWinTr[iW1]=iTr1; + if (trAll[iW1][0]->maxScore > bestScore) { + trBest=trAll[iW1][0]; + bestScore=trBest->maxScore; + }; + ++iW1; }; }; + nW=iW1; return; }; + +void ReadAlign::peOverlapChimericSEtoPE(const Transcript *seTrIn1, const Transcript *seTrIn2, Transcript *peTrOut1, Transcript *peTrOut2) { + + //convert merged into PE + Transcript tempTrChim[2]; + tempTrChim[0]=*trInit; + tempTrChim[1]=*trInit; + tempTrChim[0].peOverlapSEtoPE(peOv.mateStart,*seTrIn1); + tempTrChim[1].peOverlapSEtoPE(peOv.mateStart,*seTrIn2); + + uint segLen[2][2]; //segment length [tempTrChim][mate] + uint segEx[2];//last exon of the mate0 [tempTrChim] + uint segLmin=-1LLU, i1=0,i2=0; + for (uint ii=0; ii<2; ii++) { + segLen[ii][0]=0; + segLen[ii][1]=0; + for (uint iex=0; iextempTrChim[ii-1].exons[0][EX_G])) { + segLmin=segLen[ii][jj]; + i1=ii;//tempTrChim of the shortest segment length + i2=jj;//mate of the shortest segment length + }; + }; + }; + + if (i2==1) {//eliminate mate1: simply cut the exons that belong to mate1 + tempTrChim[i1].nExons=segEx[i1]+1; + } else {//eliminate mate 0: shift mate1 exon to the beginning + for (uint iex=0; iex -uint ReadAlign::quantTranscriptome (Transcriptome *Tr, uint nAlignG, Transcript **alignG, Transcript *alignT, vector &readTranscripts, set &readTrGenes) { +uint ReadAlign::quantTranscriptome (Transcriptome *Tr, uint nAlignG, Transcript **alignG, Transcript *alignT) { uint nAlignT=0; for (uint iag=0; iagnDel>0 || alignG[iag]->nIns>0) ) {//prevent indels if requested + Transcript *align1=alignG[iag]; + + if (!P.quant.trSAM.indel && (align1->nDel>0 || align1->nIns>0) ) { + //prevent indels if requested continue; }; - if (!P.quant.trSAM.singleEnd && (P.readNmates==2 && alignG[iag]->exons[0][EX_iFrag]==alignG[iag]->exons[alignG[iag]->nExons-1][EX_iFrag]) ) - {//prevent single end alignments + if (!P.quant.trSAM.singleEnd && (P.readNmates==2 && align1->exons[0][EX_iFrag]==align1->exons[align1->nExons-1][EX_iFrag]) ) {//not readNends: this is alignment + //prevent single end alignments continue; }; - uint nMM1=0; - char* R=Read1[alignG[iag]->roStr==0 ? 0:2]; - if (!P.quant.trSAM.softClip) {//soft clipping not allowed, extend them if possible - for (uint32 iab=0; iabnExons; iab++) { + if (!P.quant.trSAM.softClip) { + //soft clipping not allowed, extend them if possible + uint nMM1=0; + char* R=Read1[align1->roStr==0 ? 0:2]; + Transcript align2=*align1; //copy this transcript to avoid changing the original one + + for (uint32 iab=0; iabexons[iab][EX_R]; - } else if (alignG[iag]->canonSJ[iab-1]==-3) { - left1=alignG[iag]->exons[iab][EX_R]-readLength[alignG[iag]->exons[iab-1][EX_iFrag]]-1; + left1=align2.exons[iab][EX_R]; + } else if (align2.canonSJ[iab-1]==-3) { + left1=align2.exons[iab][EX_R]-readLength[align2.exons[iab-1][EX_iFrag]]-1; }; - if (iab==alignG[iag]->nExons-1) {//last block of left mates - right1=Lread-alignG[iag]->exons[iab][EX_R]-alignG[iag]->exons[iab][EX_L]; + if (iab==align2.nExons-1) {//last block of left mates + right1=Lread-align2.exons[iab][EX_R]-align2.exons[iab][EX_L]; - } else if (alignG[iag]->canonSJ[iab]==-3) {//last block of the right mate (i.e. whole read) - right1=readLength[alignG[iag]->exons[iab][EX_iFrag]]-alignG[iag]->exons[iab][EX_R]-alignG[iag]->exons[iab][EX_L]; + } else if (align2.canonSJ[iab]==-3) {//last block of the right mate (i.e. whole read) + right1=readLength[align2.exons[iab][EX_iFrag]]-align2.exons[iab][EX_R]-align2.exons[iab][EX_L]; }; for (uint b=1; b<=left1 ; b++) {//extend to the left - char r1=R[alignG[iag]->exons[iab][EX_R]-b]; - char g1=mapGen.G[alignG[iag]->exons[iab][EX_G]-b]; + char r1=R[align2.exons[iab][EX_R]-b]; + char g1=mapGen.G[align2.exons[iab][EX_G]-b]; if ( r1!=g1 && r1<4 && g1<4) ++nMM1; }; for (uint b=0; bexons[iab][EX_R]+alignG[iag]->exons[iab][EX_L]+b]; - char g1=mapGen.G[alignG[iag]->exons[iab][EX_G]+alignG[iag]->exons[iab][EX_L]+b]; + char r1=R[align2.exons[iab][EX_R]+align2.exons[iab][EX_L]+b]; + char g1=mapGen.G[align2.exons[iab][EX_G]+align2.exons[iab][EX_L]+b]; if ( r1!=g1 && r1<4 && g1<4) ++nMM1; }; - alignG[iag]->exons[iab][EX_R] -= left1; - alignG[iag]->exons[iab][EX_G] -= left1; - alignG[iag]->exons[iab][EX_L] += left1+right1; + align2.exons[iab][EX_R] -= left1; + align2.exons[iab][EX_G] -= left1; + align2.exons[iab][EX_L] += left1+right1; }; - if ( (alignG[iag]->nMM + nMM1) > min(outFilterMismatchNmaxTotal, (uint) (P.outFilterMismatchNoverLmax*(Lread-1)) ) ) { + if ( (align2.nMM + nMM1) > min(outFilterMismatchNmaxTotal, (uint) (P.outFilterMismatchNoverLmax*(Lread-1)) ) ) { //extension of soft clips yielded too many mismatches, no output continue; }; + + align1 = &align2; }; - nAlignT += Tr->quantAlign(*alignG[iag],alignT+nAlignT, readTranscripts, readTrGenes); + nAlignT += Tr->quantAlign(*align1,alignT+nAlignT); }; if (P.quant.trSAM.bamYes) {//output Aligned.toTranscriptome.bam @@ -62,18 +70,18 @@ uint ReadAlign::quantTranscriptome (Transcriptome *Tr, uint nAlignG, Transcript for (uint iatr=0;iatrunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], (imate>0 || iatr>0) ? 0 : (outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1])*2*nAlignT); }; }; }; - //not used anymore, at Colin Dewey's request + //not used anymore per Colin Dewey's request // if (nAlignT==0 && P.outSAMunmapped=="Within") {//read could be mapped to genome, but not transcriptome - output as unmapped // uint unmapType=5; // bool mateMapped[2]={false,false}; // alignBAM(*alignG[0], 0, 0, mapGen.chrStart[alignG[0]->Chr], (uint) -1, (uint) -1, 0, unmapType, mateMapped, P.outSAMattrOrder); - // for (uint imate=0; imateunsortedOneAlign(outBAMoneAlign[imate], outBAMoneAlignNbytes[imate], imate>0 ? 0 : outBAMoneAlignNbytes[0]+outBAMoneAlignNbytes[1]); // }; // diff --git a/source/ReadAlign_stitchPieces.cpp b/source/ReadAlign_stitchPieces.cpp old mode 100644 new mode 100755 index db5c3e74..990282cd --- a/source/ReadAlign_stitchPieces.cpp +++ b/source/ReadAlign_stitchPieces.cpp @@ -4,9 +4,8 @@ #include "ReadAlign.h" #include "SequenceFuns.h" #include "stitchWindowAligns.h" -#include "sjAlignSplit.cpp" +#include "sjAlignSplit.h" #include "PackedArray.h" -#include "alignSmithWaterman.h" #include "GlobalVariables.h" #include @@ -225,10 +224,11 @@ for (uint iW=0;iWswWinCovMax) swWinCovMax=swWinCov[iW]; };//if (nWA[iW]>0) };//for (uint iW=0;iW P.outFilterMultimapNmax || nTr==0) + return; //no transformation necessary + + uint32 nTr1=0; + + for (uint32 iTr=0; iTrhaploType = ( trMult[iTr]->Chr >= mapGen.nChrReal/2 ? 1 : 2 ); + + *alignsGenOut.alMult[nTr1]=*trMult[iTr];//copy information before conversion + if (trMult[iTr]->transformGenome(*mapGen.genomeOut.g, *alignsGenOut.alMult[nTr1])) { + if (trBest == trMult[iTr]) + alignsGenOut.alBest = alignsGenOut.alMult[nTr1]; //mark the best transcript + ++nTr1; + }; + }; + + if (mapGen.pGe.transform.type==2) {//diploid genome, remove identical transcripts + bool keepTr[nTr1]; + for (uint32 ia1=0; ia1haploType = 0; //undefined haplotype + alignsGenOut.alMult[ia2]->haploType = 0; + if (a1.maxScore>a2.maxScore) { + keepTr[ia2]=false; + } else { + keepTr[ia1]=false; + }; + }; + }; + }; + + alignsGenOut.alN=0; + for (uint32 ia1=0; ia1 fSet; //set of genes for this read + vector> fAlign; //gene for each alignment of this read +}; + +class ReadAnnotations { +public: + //set geneFull, geneFull_Ex50pAS, geneFull_ExonOverIntron, geneConcordant; + //uint32 geneFullTr, geneFull_Ex50pAS_Tr, geneFull_ExonOverIntron_Tr, geneConcordantTr; //index of the annotated align - for multimappers that aligned to one gene only + + //vector geneFull_Al, geneFull_Ex50pAS_Al, geneFull_ExonOverIntron_Al, geneConcordant_Al; //gene for each align + + array annotFeatures; + + vector> transcriptConcordant; + vector geneExonOverlap; + array geneVelocytoSimple;//first element is gene, then counts of transcript types + vector trVelocytoType;//first element is gene, then counts of transcript types + + //vector> sj; + //bool sjAnnot; +}; + +#endif + + diff --git a/source/STAR.cpp b/source/STAR.cpp old mode 100644 new mode 100755 index a20d7f5b..f1da6384 --- a/source/STAR.cpp +++ b/source/STAR.cpp @@ -17,37 +17,38 @@ #include "ErrorWarning.h" #include "sysRemoveDir.h" #include "BAMfunctions.h" +#include "bamSortByCoordinate.h" #include "Transcriptome.h" -#include "BAMbinSortByCoordinate.h" -#include "BAMbinSortUnmapped.h" #include "signalFromBAM.h" #include "mapThreadsSpawn.h" -#include "ErrorWarning.h" #include "SjdbClass.h" #include "sjdbInsertJunctions.h" #include "Variation.h" #include "Solo.h" +#include "samHeaders.h" -#include "bam_cat.h" +#include "twoPassRunPass1.h" #include "htslib/htslib/sam.h" #include "parametersDefault.xxd" void usage(int usageType) { - cout << "Usage: STAR [options]... --genomeDir REFERENCE --readFilesIn R1.fq R2.fq\n"; - cout <<"Spliced Transcripts Alignment to a Reference (c) Alexander Dobin, 2009-2019\n\n"; - cout <<"For more details see:\n"; - cout <<"\n"; - cout <<"\n"; + cout << "Usage: STAR [options]... --genomeDir /path/to/genome/index/ --readFilesIn R1.fq R2.fq\n"; + cout <<"Spliced Transcripts Alignment to a Reference (c) Alexander Dobin, 2009-2020\n\n"; + cout << "STAR version=" << STAR_VERSION << "\n"; + cout << "STAR compilation time,server,dir=" << COMPILATION_TIME_PLACE << "\n"; + cout << "For more details see:\n"; + cout << "\n"; + cout << "\n"; if (usageType==0) {//brief cout << "\nTo list all parameters, run STAR --help\n"; - } else {//full - cout <<'\n'<< parametersDefault; + } else if (usageType==1) {//full + cout.write(reinterpret_cast (parametersDefault), + parametersDefault_len); }; exit(0); -} - +}; int main(int argInN, char* argIn[]) { // If no argument is given, or the first argument is either '-h' or '--help', run usage() @@ -59,25 +60,38 @@ int main(int argInN, char* argIn[]) { time(&g_statsAll.timeStart); + /////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////// Parameters Parameters P; //all parameters P.inputParameters(argInN, argIn); - *(P.inOut->logStdOut) << timeMonthDayTime(g_statsAll.timeStart) << " ..... started STAR run\n" <logStdOut) << "\t" << P.commandLine << '\n'; + *(P.inOut->logStdOut) << "\tSTAR version: " << STAR_VERSION << " compiled: " << COMPILATION_TIME_PLACE << '\n'; + *(P.inOut->logStdOut) << timeMonthDayTime(g_statsAll.timeStart) << " ..... started STAR run\n" <0) {//generate original genome, in addition to the transfomed generated above + P.pGe.transform.type = 0; + P.pGe.transform.typeString = "None"; + P.pGe.transform.vcfFile = "-"; + P.pGe.gDir += "/OriginalGenome/"; + Genome genomeOrig(P, P.pGe); + genomeOrig.genomeGenerate(); + }; + + sysRemoveDir (P.outFileTmp); P.inOut->logMain << "DONE: Genome generation, EXITING\n" << flush; exit(0); - } else if (P.runMode=="liftOver") - { - for (uint ii=0; iilogMain << "DONE: lift-over of GTF file, EXITING\n" << flush; @@ -87,32 +101,25 @@ int main(int argInN, char* argIn[]) { P.inOut->logMain << "EXITING because of INPUT ERROR: unknown value of input parameter runMode=" <logProgress); - if (P.twoPass.yes) {//2-pass - //re-define P for the pass1 - - Genome mainGenome1=mainGenome; - - Parameters P1=P; - //turn off unnecessary calculations - P1.outSAMtype[0]="None"; - P1.outSAMbool=false; - P1.outBAMunsorted=false; - P1.outBAMcoord=false; - - P1.pCh.segmentMin=0; - - P1.quant.yes=false; - P1.quant.trSAM.yes=false; - P1.quant.geCount.yes=false; - P1.outSAMunmapped.within=false; - P1.quant.trSAM.bamYes=false; - - P1.outFilterBySJoutStage=0; - - P1.outReadsUnmapped="None"; - - P1.outFileNamePrefix=P.twoPass.dir; - - P1.readMapNumber=min(P.twoPass.pass1readsN, P.readMapNumber); -// P1.inOut->logMain.open((P1.outFileNamePrefix + "Log.out").c_str()); - - P1.wasp.outputMode="None"; //no WASP filtering on the 1st pass - P1.pSolo.type=0; //no solo in the first pass - - g_statsAll.resetN(); - time(&g_statsAll.timeStartMap); - P.inOut->logProgress << timeMonthDayTime(g_statsAll.timeStartMap) <<"\tStarted 1st pass mapping\n" <logStdOut << timeMonthDayTime(g_statsAll.timeStartMap) << " ..... started 1st pass mapping\n" <logProgress << timeMonthDayTime(rawtime) <<"\tFinished 1st pass mapping\n"; - *P.inOut->logStdOut << timeMonthDayTime(rawtime) << " ..... finished 1st pass mapping\n" <logStdOut << timeMonthDayTime(g_statsAll.timeStartMap) << " ..... started mapping\n" <> field1;//should check for @SQ - - if (field1!="") {//skip blank lines - samHeaderStream << line1 <<"\n"; - - stream1 >> field1; - mainGenome.chrNameAll.push_back(field1.substr(3)); - stream1 >> field1; - mainGenome.chrLengthAll.push_back((uint) stoll(field1.substr(3))); - }; - }; - extrastream.close(); - }; - - if (P.outSAMheaderPG.at(0)!="-") { - samHeaderStream << P.outSAMheaderPG.at(0); - for (uint ii=1;iioutSAM << P.samHeader; - }; - if (P.outBAMunsorted){ - outBAMwriteHeader(P.inOut->outBAMfileUnsorted,P.samHeader,mainGenome.chrNameAll,mainGenome.chrLengthAll); - }; -// if (P.outBAMcoord){ -// outBAMwriteHeader(P.inOut->outBAMfileCoord,P.samHeader,mainGenome.chrName,mainGenome.chrLength); -// }; - - if ( P.quant.trSAM.bamYes ) { - samHeaderStream.str(""); - vector trlength; - for (uint32 ii=0;iitrID.size();ii++) { - uint32 iex1=mainTranscriptome->trExI[ii]+mainTranscriptome->trExN[ii]-1; //last exon of the transcript - trlength.push_back(mainTranscriptome->exLenCum[iex1]+mainTranscriptome->exSE[2*iex1+1]-mainTranscriptome->exSE[2*iex1]+1); - samHeaderStream << "@SQ\tSN:"<< mainTranscriptome->trID.at(ii) <<"\tLN:"<outQuantBAMfile,samHeaderStream.str(),mainTranscriptome->trID,trlength); - }; - - }; - - //initialize chimeric parameters here + //initialize chimeric parameters here - note that chimeric parameters require samHeader + P.pCh.initialize(&P); + // this does not seem to work at the moment // P.inOut->logMain << "mlock value="<logMain << "Completed stage 1 mapping of outFilterBySJout mapping\n"<logStdOut << timeMonthDayTime(g_statsAll.timeFinishMap) << " ..... finished mapping\n" <chunkTr);//solo for genes + //solo counts + Solo soloMain(RAchunk,P,*RAchunk[0]->chunkTr); soloMain.processAndOutput(); if ( P.quant.geCount.yes ) {//output gene quantifications @@ -376,89 +224,8 @@ int main(int argInN, char* argIn[]) { RAchunk[0]->chunkFilesCat(P.inOut->outSAM, P.outFileTmp + "/Aligned.out.sam.chunk", g_threadChunks.chunkOutN); }; - if (P.outBAMcoord) {//sort BAM if needed - *P.inOut->logStdOut << timeMonthDayTime() << " ..... started sorting BAM\n" <logMain << timeMonthDayTime() << " ..... started sorting BAM\n" <chunkOutBAMcoord->binTotalBytes[ibin]+24*RAchunk[it]->chunkOutBAMcoord->binTotalN[ibin]; - }; - if (binS>maxMem) maxMem=binS; - }; - P.inOut->logMain << "Max memory needed for sorting = "<P.limitBAMsortRAM) { - ostringstream errOut; - errOut <<"EXITING because of fatal ERROR: not enough memory for BAM sorting: \n"; - errOut <<"SOLUTION: re-run STAR with at least --limitBAMsortRAM " <logMain, EXIT_CODE_PARAMETER, P); - } else if(maxMem==0) { - P.inOut->logMain << "WARNING: nothing to sort - no output alignments" <logMain, EXIT_CODE_PARAMETER, P); - }; - outBAMwriteHeader(bgzfOut,P.samHeaderSortedCoord,mainGenome.chrNameAll,mainGenome.chrLengthAll); - bgzf_close(bgzfOut); - } else {//sort - uint totalMem=0; - #pragma omp parallel num_threads(P.outBAMsortingThreadNactual) - #pragma omp for schedule (dynamic,1) - for (uint32 ibin1=0; ibin1chunkOutBAMcoord->binTotalN[ibin]; - binS += RAchunk[it]->chunkOutBAMcoord->binTotalBytes[ibin]; - }; - - if (binS==0) continue; //empty bin - - if (ibin == nBins-1) {//last bin for unmapped reads - BAMbinSortUnmapped(ibin,P.runThreadN,P.outBAMsortTmpDir, P, mainGenome); - } else { - uint newMem=binS+binN*24; - bool boolWait=true; - while (boolWait) { - #pragma omp critical - if (totalMem+newMem < P.limitBAMsortRAM) { - boolWait=false; - totalMem+=newMem; - }; - sleep(0.1); - }; - BAMbinSortByCoordinate(ibin,binN,binS,P.runThreadN,P.outBAMsortTmpDir, P, mainGenome); - #pragma omp critical - totalMem-=newMem;//"release" RAM - }; - }; - - //concatenate all BAM files, using bam_cat - char **bamBinNames = new char* [nBins]; - vector bamBinNamesV; - for (uint32 ibin=0; ibinlogStdOut) << timeMonthDayTime() << " ..... started wiggle output\n" <logStdOut - if (mainGenome.sharedMemory != NULL) {//need explicit call because this destructor will write to files which are deleted by 'delete P.inOut' below - delete mainGenome.sharedMemory; - mainGenome.sharedMemory = NULL; + //genomeMain.~Genome(); //need explicit call because of the 'delete P.inOut' below, which will destroy P.inOut->logStdOut + if (genomeMain.sharedMemory != NULL) {//need explicit call because this destructor will write to files which are deleted by 'delete P.inOut' below + delete genomeMain.sharedMemory; + genomeMain.sharedMemory = NULL; }; delete P.inOut; //to close files diff --git a/source/SequenceFuns.cpp b/source/SequenceFuns.cpp index f2476cb5..e9e663df 100644 --- a/source/SequenceFuns.cpp +++ b/source/SequenceFuns.cpp @@ -1,4 +1,5 @@ #include "SequenceFuns.h" +#include void complementSeqNumbers(char* ReadsIn, char* ReadsOut, uint Lread) {//complement the numeric sequences for (uint jj=0;jj3) {//N if (posN>=0) return -2; //two Ns @@ -315,16 +338,85 @@ uint localSearchNisMM(const char *x, uint nx, const char *y, uint ny, double pMM return ixBest; }; +uint32 localAlignHammingDist(const string &text, const string &query, uint32 &pos) +{ + uint32 distBest=query.size(); + if (text.size() &query, const int32 textStart, const int32 textEnd, double pMM, vector vecMM, uint32 &nMM) +{ + assert(textEnd <= (int32)textLen); + assert(textStart + (int32)query.size() >= 0); + + nMM=0; + + uint32 nMatchBest=0; + int32 posBest=textLen; + uint32 clippedL = 0; + + + int32 dirSearch = (textStart <= textEnd ? 1 : -1); //search direction + + for (int32 pos=textStart; pos!=textEnd; pos+=dirSearch) { + int32 qs = max(0, -pos); + int32 qe = min((uint32)query.size(), (uint32)(textLen-pos) ); + + uint32 nMatch1=0, nMM1=0; + + for (uint32 iq=qs; iq3) + continue; //Ns in the text are not counted as matches or mismatches + if (text[pos+iq]==query[iq]) { + nMatch1++; + } else { + nMM1++; + if ( nMM1 >= vecMM.size() ) { + nMatch1=0; + break; //too many mismatches + }; + }; + }; + + //if ( (nMatch1>nMatchBest || (nMatch1==nMatchBest && nMM1nMatchBest || (nMatch1==nMatchBest && nMM1=vecMM[nMM1]) { + posBest=pos; + nMatchBest=nMatch1; + nMM=nMM1; + clippedL = (uint32)(textStart <= textEnd ? posBest+(int32)query.size(): -posBest+(int32)textLen ); + }; + }; + + return clippedL; +}; +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +uint qualitySplit(char* r,uint L, uint maxNsplit, uint minLsplit, uint** splitR) { //splits the read r[L] by quality scores q[L], outputs in splitR - split coordinate/length - per base //returns number of good split regions uint iR=0,iS=0,iR1,LgoodMin=0, iFrag=0; while ( (iR3) ) ) { - if (r[iR]==MARK_FRAG_SPACER_BASE) iFrag++; //count read fragments + while ( iR3 ) { + if (r[iR]==MARK_FRAG_SPACER_BASE) + iFrag++; //count read fragments iR++; }; @@ -333,7 +425,7 @@ uint qualitySplit(char* r, char* q, uint L, char Qsplit, uint maxNsplit, uint m iR1=iR; //find the next bad base - while ( iR=Qsplit && r[iR]<=3 ) { + while ( iR &query, const int32 textStart, const int32 textEnd, double pMM, vector vecMM, uint32 &nMM); -uint qualitySplit(char*, char*, uint, char, uint, uint, uint**); +uint qualitySplit(char*, uint, uint, uint, uint**); int32 convertNuclStrToInt32(const string S, uint32 &intOut); string convertNuclInt32toString(const uint32 nuclNum, const uint32 L); diff --git a/source/SharedMemory.cpp b/source/SharedMemory.cpp index 26021673..2ac27b74 100644 --- a/source/SharedMemory.cpp +++ b/source/SharedMemory.cpp @@ -11,7 +11,7 @@ #include #include -#ifdef COMPILE_FOR_MAC +#if defined(COMPILE_FOR_MAC) || defined(__FreeBSD__) //some Mac's idiosyncrasies: standard SHM libraries are very old and missing some definitions #define SHM_NORESERVE 0 #endif diff --git a/source/SimpleGoodTuring/ReadMe.txt b/source/SimpleGoodTuring/ReadMe.txt new file mode 100644 index 00000000..54dd0319 --- /dev/null +++ b/source/SimpleGoodTuring/ReadMe.txt @@ -0,0 +1,72 @@ +SGT +=== + +The files here contain a C++ class for implementing simple Good-Turing +re-estimation, as described by Geoff Sampson in the book Empirical Linguistics +(2001), and on the web at http://www.grsampson.net/RGoodTur.html. The code +here is a C++ adaptation of the published code by Sampson and Gale, with the +bug fix issued in 2000. It is encapsulated as a class to allow it to be +incorporated into other programs. An additional coding change is that the data +can be presented in any order, whereas the original code required the data to +be in ascending order. + +Sampson's original code was issued with no restrictions on use. In keeping +with the spirit of this, the code here is issued under an open source licence +which allows essentially unrestricted use. + +LICENCE +------- +Copyright (c) David Elworthy 2004. +All rights reserved. + +Redistribution and use in source and binary forms for any purpose, with or +without modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the disclaimer that follows + these conditions in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Contact details +--------------- +You may contact me at david@friendlymoose.com. I would be happy to hear of any +experiences you have with the code; please feel free to send me updated +versions. The reference site for the code is http://www.friendlymoose.com/. + +Files and use +------------- +There are three files: +sgt.h SGT header file +sgttest.cpp A test and example program + +There is no source file, as the SGT class is a template over the observation +type, typically either an int or a double. + +Information about using the class is included in the header file. The code has +been tested with g++ version 3.2 on cygwin and Microsoft Visual Studio version +6 on Windows 2000. You can compile and link the test program using g++ using +the command + g++ -o sgttest sgttest.cpp + +For Visual Studio, from the command line, you can compile and link with + cl -GX sgttest.cpp + +Version history +--------------- +Initial version released January 2004. +Updated to a better implementation April 2004. diff --git a/source/SimpleGoodTuring/sgt.h b/source/SimpleGoodTuring/sgt.h new file mode 100644 index 00000000..7af50582 --- /dev/null +++ b/source/SimpleGoodTuring/sgt.h @@ -0,0 +1,300 @@ +#ifndef SGT_H +#define SGT_H +// Simple Good-Turing estimation +// +// Copyright (c) David Elworthy 2004. + +// A class for implementing simple Good-Turing re-estimation, as described by +// Geoff Sampson in the book Empirical Linguistics (2001), and on the web at +// http://www.grsampson.net/RGoodTur.html. The code here is a C++ adaptation +// of the published code by Sampson and Gale, with the bug fix issued in +// 2000. It is encapsulated as a class to allow it to be incorporated into +// other programs. An additional coding change is that the data can be +// presented in any order, whereas the original code required the data to be +// in ascending order. +// +// Copyright (c) David Elworthy 2004. +// All rights reserved. +// +// Redistribution and use in source and binary forms for any purpose, with or +// without modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions, and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions, and the disclaimer that follows +// these conditions in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +// NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// You may contact me at david@friendlymoose.com. + +#include +#include +#include +using namespace std; + +// Simple Good-Turing class. +// To use the class, create an SGT object and data to it by calling add() with +// each data point. A data point consists of the observed value and the +// frequency of the the observation (what Sampson and Gale refer to as the +// frequency, and the frequency of the the frequency). When you have added all +// the data points call analyse(). You can then call estimate() with an +// observed value as argument to get the estimated frequency for that value, +// or call iterate() to iterate over the data points. There is one special +// case to estimate(). If called with an argument of zero, it delivers the +// estimated frequency for unseen events. This is not delivered from pair(). +// To get back from the estimate value to the smoothed value of the +// observation, multiply by total(); +// +// In the original Sampson and Gale version, the observation was an integer. +// For this version, we make the code be a template over the observation type. +// However, it must always be some suitable numeric type, such as int or double. +// +// The code is implemented using the Standard Template Library (STL). + +template class SGT +{ + private: + // Data block, holding the frequency and estimate. The estimate is set up + // by analyse(). + struct Data + { + Data(unsigned int f) : freq(f), estimate(0) {} + + unsigned int freq; + double estimate; + }; + + // Internal representation, as a map from observations to frequencies. + // After calling analyse(), it provides the estimates as well. + typedef map > DataMap; + + // Minimum number of data points for a valid analysis +#ifdef _WIN32 +#define MinInput (5) +#else + static const unsigned int MinInput = 5; +#endif + + template double sq(T d) { return ((double) d)*d; } + + double smoothed(ObsType i, double intercept, double slope) + { return (exp(intercept + slope * log((double) i))); } + + public: + // Iterator type for iterate(); + typedef typename DataMap::const_iterator iterator; + + // Construct a SGT object. + SGT() : totalObs(0) {} + + // Destroy SGT object. + ~SGT() {} + + // Add a data point. + // If an observation with the same value has already been supplied, this adds + // to its frequency. + void add(ObsType observation, unsigned int frequency) + { + typename DataMap::iterator i = data.find(observation); + if (i == data.end()) + data.insert(make_pair(observation, Data(frequency))); + else + (*i).second.freq += frequency; + + totalObs += observation * frequency; + } + + // Get total number of observations (= sum of obs*freq) + ObsType total() const { return totalObs; } + + // Analyse the data. + // Returns false if there is not enough data for a valid analysis. + // In this case, the estimate is set to the original value. + bool analyse() + { + if (data.size() < MinInput) + return false; + + // The code which follows is based on S and G's analyseInput() + ObsType bigN = 0; + unsigned int rows = data.size(); + + // j could be declared in each for statement, but has to be here for + // Visual C++, which disobeys the ANSI standard on variable scope. + typename DataMap::iterator j; + for (j = data.begin(); j != data.end(); ++j) + bigN += (*j).first * (*j).second.freq; + + // Find the frequency for observation of value 1, if any + iterator row1 = row(1, data.begin()); + PZero = (row1 == data.end()) ? 0 : (*row1).second.freq / (double) bigN; + + // Set up internal arrays + vector log_obs(rows); + vector log_Z(rows); + vector rStar(rows); + + double XYs = 0, Xsquares = 0, meanX = 0, meanY = 0; + ObsType prevObs = 0; + unsigned int r = 0; + + for (j = data.begin(); j != data.end(); ++r) + { + ObsType obs = (*j).first; + Data &d = (*j).second; + + double k = (++j == data.end()) + ? (double) (2 * obs - prevObs) : (double) (*j).first; + + double Z = 2 * d.freq / (k - prevObs); + log_obs[r] = log((double) obs); + log_Z[r] = log(Z); + + meanX += log_obs[r]; + meanY += log_Z[r]; + + prevObs = obs; + } + + // Find the line with the best fit. + meanX /= rows; + meanY /= rows; + + for (r = 0; r < rows; ++r) + { + XYs += (log_obs[r] - meanX) * (log_Z[r] - meanY); + Xsquares += sq(log_obs[r] - meanX); + } + double slope = XYs / Xsquares; + double intercept = meanY - slope * meanX; + + // Now construct the estimates smoothing using the fitted line. + bool indiffValsSeen = false; + + for (j = data.begin(), r = 0; j != data.end(); ++j, ++r) + { + ObsType obs = (*j).first; + Data &d = (*j).second; + + ObsType obs1 = obs + 1; + double y = obs1 * smoothed(obs1, intercept, slope) + / smoothed(obs, intercept, slope); + + iterator nextRow = row(obs1, j); + if (nextRow == data.end()) + { + indiffValsSeen = true; + } + else if (!indiffValsSeen) + { + unsigned int next_n = (*nextRow).second.freq; + unsigned int freq = d.freq; + + double x = obs1 * next_n / (double) freq; + if (fabs(x - y) <= 1.96 * sqrt(sq(obs1) * next_n + / (sq(freq)) * (1 + next_n / (double) freq))) + { + indiffValsSeen = true; + } + else + { + rStar[r] = x; + } + } + + if (indiffValsSeen) + { + rStar[r] = y; + } + } + + double bigNprime = 0.0; + for (j = data.begin(), r = 0; j != data.end(); ++j, ++r) + bigNprime += (*j).second.freq * rStar[r]; + + for (j = data.begin(), r = 0; j != data.end(); ++j, ++r) + (*j).second.estimate = (1 - PZero) * rStar[r] / bigNprime; + + return true; + } + + // Analyze the data. + // This just calls analyse(), and is included as a concession to speakers + // of debased dialects of English. + void analyze() { analyse(); } + + // Get the estimate for an observation. + // If there was no such observation, return false. + // Otherwise return true and yield the estimate. + bool estimate(ObsType observation, double &estimate) const + { + if (observation == 0) + { + estimate = PZero; + return true; + } + + iterator rownum = row(observation, data.begin()); + if (rownum == data.end()) + { + return false; + } + + estimate = (*rownum).second.estimate; + return true; + } + + // Get start and end iterators over the data map. + // You do not derefence these iterators directly, but instead used the + // access functions, obs, freq and estimate. + pair iterate() const + { return make_pair(data.begin(), data.end()); } + + // Get the observation from an iterator. + ObsType obs(iterator i) const { return (*i).first; } + + // Get the frequency from an iterator (as supplied by add). + unsigned int freq(iterator i) const { return (*i).second.freq; } + + // Get the estimated relative frequency from an iterator. + double estimate(iterator i) const { return (*i).second.estimate; } + + private: + // The data points + DataMap data; + + // Zero estimate (only valid after a call to analyse()). + double PZero; + + // Total number of observations + ObsType totalObs; + + // Find the last row of the data which has a value equals to obs. + // If there is no such value, return data.end(). + // start is a hint about where to start searching. + iterator row(ObsType obs, iterator start) const + { + iterator j = start; + + while (j != data.end() && (*j).first < obs) + ++j; + + return ((j != data.end() && (*j).first == obs) ? j : data.end()); + } +}; + +#endif //SGT_H diff --git a/source/Solo.cpp b/source/Solo.cpp old mode 100644 new mode 100755 index e63b2bba..30af8e4f --- a/source/Solo.cpp +++ b/source/Solo.cpp @@ -1,23 +1,87 @@ #include "Solo.h" +#include "TimeFunctions.h" +#include "streamFuns.h" Solo::Solo(ReadAlignChunk **RAchunkIn, Parameters &Pin, Transcriptome &inTrans) - : RAchunk(RAchunkIn), P(Pin), pSolo(P.pSolo), Trans(inTrans) + : RAchunk(RAchunkIn), P(Pin), Trans(inTrans), pSolo(P.pSolo) { - if (pSolo.type==0 ) + if ( pSolo.type == 0 ) + return; + + readBarSum = new SoloReadBarcode(P); + + if ( pSolo.type == pSolo.SoloTypes::CB_samTagOut ) return; soloFeat = new SoloFeature*[pSolo.nFeatures]; for (uint32 ii=0; iilogStdOut << timeMonthDayTime(timeCurrent) << " ..... starting SoloCellFiltering" <loadRawMatrix(); + soloFeat[0]->cellFiltering(); + + time( &timeCurrent); + *P.inOut->logStdOut << timeMonthDayTime(timeCurrent) << " ..... finished successfully\n" <logMain << "ALL DONE!\n" << flush; + exit(0); +}; + + //////////////////////////////////////////////////////////////////////////////////// void Solo::processAndOutput() { if (pSolo.type==0 ) - return; + return; + + {//collect barcode statistics + if (pSolo.cbWLyes) {//now we can define WL and counts + for (int ii=0; iiaddCounts(*RAchunk[ii]->RA->soloRead->readBar); + readBarSum->addStats(*RAchunk[ii]->RA->soloRead->readBar); + }; + }; + + ofstream *statsStream = &ofstrOpen(P.outFileNamePrefix+pSolo.outFileNames[0]+"Barcodes.stats",ERROR_OUT, P); + readBarSum->statsOut(*statsStream); + statsStream->close(); + + //pseudocounts + if (pSolo.CBmatchWL.mm1_multi_pc) { + for (uint32 ii=0; iicbReadCountExact[ii]++;//add one to exact counts + }; + }; + }; + + if (pSolo.type==pSolo.SoloTypes::CB_samTagOut) + return; + + {//process all features + *P.inOut->logStdOut << timeMonthDayTime() << " ..... started Solo counting\n" <logMain << timeMonthDayTime() << " ..... started Solo counting\n" <processRecords(); + }; - for (uint32 ii=0; iiprocessRecords(RAchunk); + *P.inOut->logStdOut << timeMonthDayTime() << " ..... finished Solo counting\n" <logMain << timeMonthDayTime() << " ..... finished Solo counting\n" < &wl, vector &wlEd1, vector &wlInd1); + +void SoloBarcode::sortWhiteList(ParametersSolo *pSolo) +{ + totalSize=0; + minLen=(uint32)-1; + wlAdd.resize( wl.size() ); + if (pSolo->CBmatchWL.ParseBio_ED3) { + wlEd.resize( wl.size() ); + wlEdInd.resize( wl.size() ); + }; + + for (uint32 ilen1=1; ilen1 < wl.size(); ilen1++) {//scan through different lengths for this CB + wlAdd[ilen1]=totalSize; + if (wl[ilen1].size()>0) { + if (ilen1CBmatchWL.ParseBio_ED3) {//add mismatches + wlAddMismatches(3, ilen1, wl[ilen1], wlEd[ilen1], wlEdInd[ilen1]); + }; + + }; + }; +}; + +void SoloBarcode::extractPositionsFromString(string &strIn) +{ + vector p(4); + splitString(strIn,'_',p); + anchorType[0] = std::stoi(p[0]); + anchorType[1] = std::stoi(p[2]); + anchorDist[0] = std::stoi(p[1]); + anchorDist[1] = std::stoi(p[3]); +}; + +void wlAddMismatches(uint32 nMM, uint32 cbLen, vector &wl, vector &wlEd1, vector &wlEdInd1) +{ + struct type_cbMMind { + uintCB cb; + uint32 ind; + uint32 mm; + }; + + //max size + uint64 ntot=wl.size()*(std::pow(cbLen*3,nMM+1)-1)/(cbLen*3-1); //geometric series 1+L+L*L+... + + vector cbMMind; + cbMMind.reserve(ntot); + + for (uint32 icb=0; icb>2; + uintCB cbmmd = (cbmm & maskd) | ((cbmm & maskd1)>>2); + //cout << convertNuclInt64toString(cbmmd, cbLen)<>2; + //cout << convertNuclInt64toString(mask, cbLen)< nCBmm(nMM+1,0); + uintCB prevCB = (uintCB)(-1); + for (uint64 ii=0; ii0 && cbMMind[ii].cb == prevCB ) + || ( ii> wl;//whitelists, one for each length + vector> wlEd;//edited whitelists (i.e. including mismatches and indels) + vector> wlEdInd;//index for wlEd in the unedited wl + + uint64 wlFactor;//factor and modulo for converting each whitelist index into global index + vector wlAdd;//additive for each length + uint32 minLen;//minimum length for this barcode + uint32 totalSize;//total size of all whitelists + + uint64 iLen, iCB;//indexes, used in ParametersSolo.cpp + + bool extractBarcode(string &seqIn, string &qualIn, const uint32 aStart, string &bSeq, string &bQual); + void sortWhiteList(ParametersSolo *pSolo); + void extractPositionsFromString(string &strIn); + + //SoloBarcode(ParametersSolo *pSolo) : pSolo(pSolo) {}; +}; + +#endif \ No newline at end of file diff --git a/source/SoloBarcode_extractBarcode.cpp b/source/SoloBarcode_extractBarcode.cpp new file mode 100755 index 00000000..bf1a5cac --- /dev/null +++ b/source/SoloBarcode_extractBarcode.cpp @@ -0,0 +1,34 @@ +#include "SoloBarcode.h" +#include + +bool SoloBarcode::extractBarcode(string &seqIn, string &qualIn, const uint32 adapterStart, string &bSeq, string &bQual) +{//input: sequence seqIn, adapter start adapterStart + //output: start position of the barcode + array pos={0,0}; + for (uint32 ii=0; ii<2; ii++) { + switch (anchorType[ii]) {//this calculates the position of the anchor base + case 0: //read start + pos[ii]=0; + break; + case 1: //read end + pos[ii]=seqIn.size()-1; + break; + case 2: //adapter start + pos[ii]=(int32)adapterStart; + break; + case 3: //adapter end + pos[ii]=(int32)adapterStart+adapterLength-1; + break; + }; + pos[ii]+=anchorDist[ii]; + }; + + bSeq=""; + bQual=""; + if (pos[0]<0 || pos[1]>(int32)seqIn.size() || pos[0]>pos[1]) //something went wrong + return false; + + bSeq =seqIn.substr(pos[0],pos[1]-pos[0]+1); + bQual=qualIn.substr(pos[0],pos[1]-pos[0]+1); + return true; +}; diff --git a/source/SoloCommon.h b/source/SoloCommon.h new file mode 100644 index 00000000..8e3756fe --- /dev/null +++ b/source/SoloCommon.h @@ -0,0 +1,23 @@ +#ifndef H_SoloCommon +#define H_SoloCommon + +typedef struct{ + uint64 cb; + uint32 umi; +} readInfoStruct; + +typedef struct{ + uint32 tr; + uint8 type; +} trTypeStruct; + +typedef uint32 uintUMI; +typedef uint64 uintCB; +typedef uint32 uintRead; + +#define uintUMIbits 32 +#define velocytoTypeGeneBits 4 +#define velocytoTypeGeneBitShift 28 +#define geneMultMark (((uint32)1)<<31) + +#endif \ No newline at end of file diff --git a/source/SoloFeature.cpp b/source/SoloFeature.cpp old mode 100644 new mode 100755 index 77aa9f7f..fc2605ad --- a/source/SoloFeature.cpp +++ b/source/SoloFeature.cpp @@ -1,17 +1,27 @@ #include "SoloFeature.h" #include "streamFuns.h" -SoloFeature::SoloFeature(int feTy, Parameters &Pin, Transcriptome &inTrans) - : featureType(feTy), P(Pin), pSolo(P.pSolo), Trans(inTrans) +SoloFeature::SoloFeature(Parameters &Pin, ReadAlignChunk **RAchunk, Transcriptome &inTrans, int32 feTy, SoloReadBarcode *readBarSumIn, SoloFeature **soloFeatAll) + : P(Pin), RAchunk(RAchunk), Trans(inTrans), featureType(feTy), soloFeatAll(soloFeatAll), pSolo(P.pSolo), readBarSum(readBarSumIn) { - - readFeatSum = new SoloReadFeature(featureType,P,-1); - readBarSum = new SoloReadBarcode(P); - readFeatAll = new SoloReadFeature*[P.runThreadN]; - readBarAll = new SoloReadBarcode*[P.runThreadN]; - - if (pSolo.type==0) - return; - - statsStream = &ofstrOpen(P.outFileNamePrefix+pSolo.outFileNames[0]+pSolo.featureNames[featureType]+".stats",ERROR_OUT, P); + if (featureType>=0) {//otherwise we do not need these arrays - e.g. with --runMode soloCellFiltering + readFeatSum = new SoloReadFeature(featureType,P,-1); + readFeatAll = new SoloReadFeature*[P.runThreadN]; + }; + + //number of features + switch (featureType) { + case SoloFeatureTypes::Gene : + case SoloFeatureTypes::GeneFull : + case SoloFeatureTypes::GeneFull_Ex50pAS : + case SoloFeatureTypes::GeneFull_ExonOverIntron : + case SoloFeatureTypes::Velocyto : + featuresNumber=Trans.nGe; + break; + case SoloFeatureTypes::SJ : + featuresNumber=P.sjAll[0].size(); + break; + default: + featuresNumber = -1; //undefined + }; }; diff --git a/source/SoloFeature.h b/source/SoloFeature.h old mode 100644 new mode 100755 index 3c96635b..bfca1c45 --- a/source/SoloFeature.h +++ b/source/SoloFeature.h @@ -1,45 +1,101 @@ #ifndef H_SoloFeature #define H_SoloFeature + +#include +#include +#include + #include "IncludeDefine.h" #include "ReadAlignChunk.h" #include "Transcriptome.h" -#include +#include "SoloCommon.h" #include "SoloRead.h" +#include "ReadAlignChunk.h" + +#include "SoloFilteredCells.h" class SoloFeature { +private: + Parameters &P; + ReadAlignChunk **RAchunk; + Transcriptome &Trans; + + const int32 featureType; + SoloFeature **soloFeatAll; + + static const uint32 umiArrayStride=3; + enum {rguG, rguU, rguR}; + uint32 rguStride; + public: + ParametersSolo &pSolo; SoloReadFeature *readFeatSum, **readFeatAll; - SoloReadBarcode *readBarSum, **readBarAll; + SoloReadBarcode *readBarSum; - uint64 nReadsMapped, nCB; //total number of mapped reads + uint64 nReadsMapped, nReadsInput; //total number of mapped reads + uint32 nCB; + uint32 featuresNumber; //number of features (i.e. genes, SJs, etc) uint32 *rGeneUMI;//mapped reads sorted by CB - uint32 *indCB;//index of detected CBs in the whitelist uint32 *rCBn;//number of reads for detected CBs in the whitelist uint32 **rCBp;//array of pointers to each CB sub-array - uint32 *nUperCB;//number of UMIs per CB - uint32 *nGperCB;//number of genes (with >0 UMIs) per CB - uint32 nCellGeneEntries;//total number of non-zero cell/gene combinations (entries in the output matrix) - - ofstream *statsStream; + vector indCB;//index of detected CBs in the whitelist + vector indCBwl; //reverse of indCB: index of WL CBs in detected CB list + vector nUMIperCB, nUMIperCBsorted;//number of UMIs per CB, and the same sorted (descendant) + vector nGenePerCB;//number of genes (with >0 UMIs) per CB + vector nReadPerCB;//number of reads per CB. With multimappers: all aligns per CB + vector nReadPerCBunique, nReadPerCBtotal; //number of unique and multiple reads per CB + + vector countCellGeneUMI;//sparsified matrix for the counts, each entry is: geneID count1 count2 ... countNcounts + vector countCellGeneUMIindex;//index of CBs in the count matrix + uint32 countMatStride; //number of counts per entry in the count matrix + + struct { + vector m; + vector i; + uint32 s; + } countMatMult; + + vector>> cbFeatureUMImap; //for SmartSeq counting + + string outputPrefix, outputPrefixFiltered; + + SoloFilteredCells filteredCells; + array,2> sjAll; + + vector readInfo; //corrected CB/UMI information for each read + + vector redistrFilesCBindex, redistrFilesCBfirst; //redistr file for each CB, CB boundaries in redistributed files + vector redistrFilesNreads; //number of reads in each file + vector redistrFilesStreams; - SoloFeature(int feTy, Parameters &Pin, Transcriptome &inTrans); - void processRecords(ReadAlignChunk **RAchunk); - void collapseUMI(uint32 *rGU, uint32 rN, uint32 &nGenes, uint32 &nUtot, uint32 *umiArray); - void outputResults(); + SoloFeature(Parameters &Pin, ReadAlignChunk **RAchunk, Transcriptome &inTrans, int32 feTy, SoloReadBarcode *readBarSumIn, SoloFeature **soloFeatAll); + void processRecords(); + void sumThreads(); + void countSmartSeq(); + void countCBgeneUMI(); + void countVelocyto(); + void quantTranscript(); + + void collapseUMI(uint32 iCB, uint32 *umiArray); + void collapseUMI_CR(uint32 iCB, uint32 *umiArray); + void collapseUMIall(uint32 iCB, uint32 *umiArray); + uint32 umiArrayCorrect_CR (const uint32 nU0, uintUMI *umiArr, const bool readInfoRec, const bool nUMIyes, unordered_map &umiCorr); + uint32 umiArrayCorrect_Directional(const uint32 nU0, uintUMI *umiArr, const bool readInfoRec, const bool nUMIyes, unordered_map &umiCorr, const int32 dirCountAdd); + uint32 umiArrayCorrect_Graph (const uint32 nU0, uintUMI *umiArr, const bool readInfoRec, const bool nUMIyes, unordered_map &umiCorr); -private: - const int32 featureType; - - Parameters &P; - ParametersSolo &pSolo; - Transcriptome &Trans; - - static const uint32 umiArrayStride=3; + void outputResults(bool cellFilterYes, string outputPrefixMat); + void addBAMtags(char *&bam0, uint32 &size0, char* bam1); + void statsOutput(); + void redistributeReadsByCB(); + + void cellFiltering(); + void emptyDrops_CR(); + void loadRawMatrix(); }; #endif diff --git a/source/SoloFeatureTypes.h b/source/SoloFeatureTypes.h new file mode 100644 index 00000000..2dd736a8 --- /dev/null +++ b/source/SoloFeatureTypes.h @@ -0,0 +1,12 @@ +#ifndef H_SoloFeatureTypes +#define H_SoloFeatureTypes + +namespace SoloFeatureTypes +{ +// enum {Gene=0, GeneFull=1, SJ=2, Transcript3p=3, VelocytoSpliced=4, VelocytoUnspliced=5, VelocytoAmbiguous=6, N=7}; +// const static vector Names={"Gene","GeneFull","SJ","Transcript3p","VelocytoSpliced","VelocytoUnspliced","VelocytoAmbiguous",}; + enum {SJ=0, Transcript3p=1, GeneFull=2, GeneFull_ExonOverIntron=3, GeneFull_Ex50pAS=4, Gene=5, VelocytoSimple=6, Velocyto=7, N=8}; + const static vector Names={"SJ", "Transcript3p", "GeneFull", "GeneFull_ExonOverIntron", "GeneFull_Ex50pAS", "Gene", "VelocytoSimple", "Velocyto"}; +}; + +#endif \ No newline at end of file diff --git a/source/SoloFeature_addBAMtags.cpp b/source/SoloFeature_addBAMtags.cpp new file mode 100644 index 00000000..7c675693 --- /dev/null +++ b/source/SoloFeature_addBAMtags.cpp @@ -0,0 +1,26 @@ +#include "SoloFeature.h" +#include "BAMfunctions.h" +#include "SequenceFuns.h" + +void SoloFeature::addBAMtags(char *&bam0, uint32 &size0, char *bam1) +{//add extra tags to the BAM record + + uint64 iread = * ((uint64*) (bam0+size0)); + iread = iread >> 32; //iRead was encoded in the upper 32 bitsls + + string cb="-"; + string umi="-"; + if (readInfo[iread].cb+1 != 0) + cb = pSolo.cbWLstr[readInfo[iread].cb]; + + if (readInfo[iread].umi+1 != 0) + umi = convertNuclInt64toString(readInfo[iread].umi, pSolo.umiL); + + memcpy(bam1, bam0, size0); + + size0 += bamAttrArrayWrite(cb, "CB", bam1+size0); + size0 += bamAttrArrayWrite(umi, "UB", bam1+size0); + uint32 *bam1i = (uint32*) bam1; + bam1i[0] = size0-sizeof(uint32); + bam0=bam1; +}; \ No newline at end of file diff --git a/source/SoloFeature_cellFiltering.cpp b/source/SoloFeature_cellFiltering.cpp new file mode 100644 index 00000000..6349a3ca --- /dev/null +++ b/source/SoloFeature_cellFiltering.cpp @@ -0,0 +1,132 @@ +#include "SoloFeature.h" +#include "serviceFuns.cpp" +#include + +void SoloFeature::cellFiltering() +{ + + if (pSolo.cellFilter.type[0]=="None" || nCB<1) {//no filtering, or no cells to filter + return; + }; + + switch(featureType) { + default: + return; //filtering not done for other features + + case SoloFeatureTypes::Velocyto: { + filteredCells.reset(nCB); + + //Velocyto: use filter from Gene + SoloFeature &soFeGe= *soloFeatAll[pSolo.featureInd[SoloFeatureTypes::Gene]]; + for (uint32 ic=0; icu2;} ); //sort descending + break; + }; + case SoloFeatureTypes::Gene: + case SoloFeatureTypes::GeneFull: + case SoloFeatureTypes::GeneFull_Ex50pAS: + case SoloFeatureTypes::GeneFull_ExonOverIntron: + case -1: //undefined: matrix loaded from file + { + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// cell calling (filtering) + //do the filtering + + //simple filtering first + nUMIperCBsorted=nUMIperCB; + std::sort( nUMIperCBsorted.begin(), nUMIperCBsorted.end(), [](const uint32_t &u1, const uint32_t &u2) {return u1>u2;} ); //sort descending + + uint32 nUMImax=0, nUMImin=0; + if (pSolo.cellFilter.type[0]=="TopCells") { + nUMImin = nUMIperCBsorted[min(nCB-1,pSolo.cellFilter.topCells)]; + } else {//other filtering types require simple filtering first + //find robust max + uint32 maxind=int(round(pSolo.cellFilter.knee.nExpectedCells*(1.0-pSolo.cellFilter.knee.maxPercentile)));//cell number for robust max + nUMImax = nUMIperCBsorted[min(nCB-1,maxind)];//robust estimate of the max UMI + nUMImin = int(round(nUMImax/pSolo.cellFilter.knee.maxMinRatio)); + }; + nUMImin=max(nUMImin,(uint32) 1);//cannot be zero + + filteredCells.reset(nCB); //all stats to 0 + + for (uint32 icb=0; icb=nUMImin) { + filteredCells.filtVecBool[icb]=true; + filteredCells.nCellsSimple++; + }; + }; + + P.inOut->logMain << "cellFiltering: simple: nUMImax="<< nUMImax <<"; nUMImin="<< nUMImin <<"; nCellsSimple="<< filteredCells.nCellsSimple <0) {//for CellFiltering only, read information is not available + filteredCells.nReadInCells += nReadPerCBtotal[icb]; + filteredCells.nReadInCellsUnique += nReadPerCBunique[icb]; + filteredCells.nReadPerCellUnique.push_back(nReadPerCBunique[icb]); + }; + + uint32 ng1 = 0; //number of genes detected in this cell + for (uint32 ig=0; ig 0) { + geneDetected[countCellGeneUMI[indG1]] = true; //gene is present if it's count > 0 for + ng1++; + }; + }; + + filteredCells.nGeneInCells += ng1; //had to recalculate this since some gene counts could be 0 + filteredCells.nGenePerCell.push_back(ng1); + }; + }; + + if (filteredCells.nCells==0) {//all stats were already set to 0 + return; + }; + + filteredCells.nGeneDetected=0; + for (uint32 ii=0; ii> &vC) -{ - const uint32 bitTop=1<<31; - const uint32 bitTopMask=~bitTop; - - for (uint32 iu=0; iu umiMaskLow) - break; //upper half is different - - if (uuXor >> (__builtin_ctz(uuXor)/2)*2 > 3) //shift by even number of trailing zeros - continue;//>1MM - - //1MM UMI - - //graph coloring - if ( rGU[iu+2] == def_MarkNoColor && rGU[iuu+2] == def_MarkNoColor ) {//no color - //new color - rGU[iu+2] = nC; - rGU[iuu+2] = nC; - ++nC; - nU1 -= 2;//subtract the duplicated UMIs - } else if ( rGU[iu+2] == def_MarkNoColor ) { - rGU[iu+2] = rGU[iuu+2]; - --nU1;//subtract the duplicated UMIs - } else if ( rGU[iuu+2] == def_MarkNoColor ) { - rGU[iuu+2] = rGU[iu+2]; - --nU1;//subtract the duplicated UMIs - } else {//both color - if (rGU[iuu+2] != rGU[iu+2]) {//color conflict - //uint32 p[2]={rGU[iu+2],rGU[iuu+2]}; - vC.push_back({rGU[iu+2],rGU[iuu+2]}); - //vC.push_back({rGU[iuu+2],rGU[iu+2]}); - }; - }; - - //directional collapse - if ( (rGU[iuu+1] & bitTop) == 0 && (rGU[iu+1] & bitTopMask)>(2*(rGU[iuu+1] & bitTopMask)-1) ) {//iuu is duplicate of iu - rGU[iuu+1] |= bitTop; - --nU2;//subtract the duplicated UMIs - } else if ( (rGU[iu+1] & bitTop) == 0 && (rGU[iuu+1] & bitTopMask)>(2*(rGU[iu+1] & bitTopMask)-1) ) {//iu is duplicate of iuu - rGU[iu+1] |= bitTop; - --nU2;//subtract the duplicated UMIs - }; - }; - }; -}; - -void graphDepthFirstSearch(uint32 n, vector &nodeVisited, vector> &nodeEdges) { - for (const auto &nn : nodeEdges[n]) { - if (!nodeVisited[nn]) { - nodeVisited[nn]=true; - graphDepthFirstSearch(nn,nodeVisited,nodeEdges); - }; - }; -}; - -uint32 graphNumberOfConnectedComponents(uint32 N, vector> V) {//find number of connected components - //N=number of nodes - //V=edges, list of connected nodes, each pair of nodes listed once - //simple recursive DFS - - //sort -// qsort(V.data(),V.size(),2*sizeof(uint32),funCompareNumbers); - if (V.size()==0) - return N; - - vector> nodeEdges (N); - for (uint32 ii=0; ii nodeVisited(N,false); - - uint32 nConnComp=0; - for (uint32 ii=0; ii); //sort by gene number - - //compact reads per gene - uint32 gid1=-1;//current gID - nGenes=0; //number of genes - uint32 *gID = new uint32[min(Trans.nGe,rN)+1]; //gene IDS - uint32 *gReadS = new uint32[min(Trans.nGe,rN)+1]; //start of gene reads TODO: allocate this array in the 2nd half of rGU - for (uint32 iR=0; iR<2*rN; iR+=2) { - if (rGU[iR]!=gid1) {//record gene boundary - gReadS[nGenes]=iR; - gid1=rGU[iR]; - gID[nGenes]=gid1; - ++nGenes; - }; - rGU[iR]=rGU[iR+1]; //shift UMIs - //rGU[iR+1] storage this will be used later for counting - }; - gReadS[nGenes]=2*rN;//so that gReadS[nGenes]-gReadS[nGenes-1] is the number of reads for nGenes - - uint32 *nUg = new uint32[nGenes*3];//3 types of counts - nUtot=0; - for (uint32 iG=0; iG); - - //exact collapse - uint32 iR1=-umiArrayStride; //number of distinct UMIs for this gene - uint32 u1=-1; - for (uint32 iR=0; iRnRumiMax) nRumiMax=umiArray[iR1+1]; - }; - uint32 nU0=(iR1+umiArrayStride)/umiArrayStride; - - //collapse with 1MM - uint32 nU1=nU0, nU2=nU0;//2 types of 1MM collapsing - uint32 nC=0; //graph colors - vector> vC;//color connections - - collapseUMIwith1MMlowHalf(umiArray, umiArrayStride, pSolo.umiMaskLow, nU0, nU1, nU2, nC, vC); - - //exchange low and high half of UMIs, re-sort, and look for 1MM again - for (uint32 iu=0; iu>(pSolo.umiL); - umiArray[iu] &= pSolo.umiMaskLow; //remove high - umiArray[iu] <<= (pSolo.umiL); //move low to high - umiArray[iu] |= high; //add high - }; - qsort(umiArray, nU0, umiArrayStride*sizeof(uint32), funCompareNumbers); - collapseUMIwith1MMlowHalf(umiArray, umiArrayStride, pSolo.umiMaskLow, nU0, nU1, nU2, nC, vC); - - nUg[3*iG]=nU0; - nUg[3*iG+1]=nU1+graphNumberOfConnectedComponents(nC,vC); - nUg[3*iG+2]=nU2; - nUtot+=nUg[3*iG+1]; - }; - - uint32 *rGUp=rGU; - for (uint32 iG=0; iG1) {//record 2 more counts - rGUp[2]=nUg[3*iG+1]; - rGUp[3]=nUg[3*iG+2]; - rGUp += 4; - } else {//only one count recorded, save space - rGUp += 2; - }; - }; - //cout << nRumiMax << '\n'; - -}; diff --git a/source/SoloFeature_collapseUMI_Graph.cpp b/source/SoloFeature_collapseUMI_Graph.cpp new file mode 100644 index 00000000..fa8a6b17 --- /dev/null +++ b/source/SoloFeature_collapseUMI_Graph.cpp @@ -0,0 +1,172 @@ +#include "SoloFeature.h" +#include "streamFuns.h" +#include "TimeFunctions.h" +#include "serviceFuns.cpp" +#include +#include "SoloCommon.h" +#include + +#define def_MarkNoColor (uint32) -1 + +void collapseUMIwith1MMlowHalf(uint32 *umiArr, uint32 umiArrayStride, uint32 umiMaskLow, uint32 nU0, uint32 &nU1, uint32 &nU2, uint32 &nC, vector> &vC); +void graphDepthFirstSearch(uint32 n, vector> &nodeEdges, vector &nodeColor); +uint32 graphNumberOfConnectedComponents(uint32 N, vector> V, vector &nodeColor); + + +uint32 SoloFeature::umiArrayCorrect_Graph(const uint32 nU0, uintUMI *umiArr, const bool readInfoRec, const bool nUMIyes, unordered_map &umiCorr) +{ + uint32 nU1 = nU0; + uint32 nU2 = nU0; + uint32 graphN = 0; //number of nodes + vector> graphConn;//node connections + vector graphComp;//for each node (color) - connected component number + + for (uint64 iu=0; iu); + collapseUMIwith1MMlowHalf(umiArr, umiArrayStride, pSolo.umiMaskLow, nU0, nU1, nU2, graphN, graphConn); + + //exchange low and high half of UMIs, re-sort, and look for 1MM again + for (uint32 iu=0; iu); + collapseUMIwith1MMlowHalf(umiArr, umiArrayStride, pSolo.umiMaskLow, nU0, nU1, nU2, graphN, graphConn); + + uint32 nConnComp=graphNumberOfConnectedComponents(graphN, graphConn, graphComp); + nU1 += nConnComp; + + if (readInfoRec) { + for (uint32 ii=0; ii> umiBest(graphN,{0,0}); + unordered_map umiCorrColor; + for (uint32 iu=0; iu0 ) + umiCorr[umi]=umiBest[umiCorrColor[umi]][1]; + }; + }; + + if (nUMIyes) {//this is not needed + return nU1; + } else { + return 0; + }; + +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////// +void collapseUMIwith1MMlowHalf(uint32 *umiArr, uint32 umiArrayStride, uint32 umiMaskLow, uint32 nU0, uint32 &nU1, uint32 &nU2, uint32 &nC, vector> &vC) +{ + const uint32 bitTop=1<<31; + const uint32 bitTopMask=~bitTop; + + for (uint32 iu=0; iu umiMaskLow) + break; //upper half is different + + if (uuXor >> (__builtin_ctz(uuXor)/2)*2 > 3) //shift by even number of trailing zeros + continue;//>1MM + + //1MM UMI + + //graph coloring + if ( umiArr[iu+2] == def_MarkNoColor && umiArr[iuu+2] == def_MarkNoColor ) {//no color + //new color + umiArr[iu+2] = nC; + umiArr[iuu+2] = nC; + ++nC; + nU1 -= 2;//subtract the duplicated UMIs + } else if ( umiArr[iu+2] == def_MarkNoColor ) { + umiArr[iu+2] = umiArr[iuu+2]; + --nU1;//subtract the duplicated UMIs + } else if ( umiArr[iuu+2] == def_MarkNoColor ) { + umiArr[iuu+2] = umiArr[iu+2]; + --nU1;//subtract the duplicated UMIs + } else {//both color + if (umiArr[iuu+2] != umiArr[iu+2]) {//color conflict + //uint32 p[2]={umiArr[iu+2],umiArr[iuu+2]}; + vC.push_back({umiArr[iu+2],umiArr[iuu+2]}); + //vC.push_back({umiArr[iuu+2],umiArr[iu+2]}); + }; + }; + + //"directional" collapse from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017). + if ( (umiArr[iuu+1] & bitTop) == 0 && (umiArr[iu+1] & bitTopMask)>(2*(umiArr[iuu+1] & bitTopMask)-1) ) {//iuu is duplicate of iu + umiArr[iuu+1] |= bitTop; + --nU2;//subtract the duplicated UMIs + } else if ( (umiArr[iu+1] & bitTop) == 0 && (umiArr[iuu+1] & bitTopMask)>(2*(umiArr[iu+1] & bitTopMask)-1) ) {//iu is duplicate of iuu + umiArr[iu+1] |= bitTop; + --nU2;//subtract the duplicated UMIs + }; + }; + }; +}; + +void graphDepthFirstSearch(uint32 n, vector> &nodeEdges, vector &nodeColor) +{ + for (const auto &nn : nodeEdges[n]) { + if (nodeColor[nn]==(uint32)-1) {//node not visited + nodeColor[nn]=nodeColor[n]; + graphDepthFirstSearch(nn,nodeEdges,nodeColor); + }; + }; +}; + +uint32 graphNumberOfConnectedComponents(uint32 N, vector> V, vector &nodeColor) +{//find number of connected components + //N=number of nodes + //V=edges, list of connected nodes, each pair of nodes listed once + //simple recursive DFS + + nodeColor.resize(N,(uint32)-1); //new color (connected component) for each node (each original color) + + if (V.size()==0) + return N; + + vector> nodeEdges (N); + for (uint32 ii=0; ii +#include "SoloCommon.h" + +inline int funCompareSolo1 (const void *a, const void *b) { + uint32 *va= (uint32*) a; + uint32 *vb= (uint32*) b; + + if (va[1]>vb[1]) { + return 1; + } else if (va[1]vb[0]){ + return 1; + } else if (va[0]); //sort by gene index + + //compact reads per gene + uint32 gid1=-1;//current gID + uint32 nGenes=0; //number of genes + uint32 *gID = new uint32[min(featuresNumber,rN)+1]; //gene IDs + uint32 *gReadS = new uint32[min(featuresNumber,rN)+1]; //start of gene reads TODO: allocate this array in the 2nd half of rGU + for (uint32 iR=0; iR umiMaxGeneCount;//for each umi, max counts of reads per gene + + unordered_map > umiGeneHash, umiGeneHash0; + //UMI //Gene //Count + if (pSolo.umiFiltering.MultiGeneUMI) { + for (uint32 iR=0; iRig.second) + ig.second=0; //kills Gene with read count *strictly* < maximum count + }; + }; + }; + + vector> umiCorrected(nGenes); + + if (countCellGeneUMI.size() < countCellGeneUMIindex[iCB] + nGenes*countMatStride) + countCellGeneUMI.resize((countCellGeneUMI.size() + nGenes*countMatStride )*2);//allocated vector too small + + nGenePerCB[iCB]=0; + nUMIperCB[iCB]=0; + countCellGeneUMIindex[iCB+1]=countCellGeneUMIindex[iCB]; + ///////////////////////////////////////////// + /////////// main cycle over genes + for (uint32 iG=0; iG); + + //exact collapse + uint32 iR1=-umiArrayStride; //number of distinct UMIs for this gene + uint32 u1=-1; + for (uint32 iR=rguU; iRnRumiMax) nRumiMax=umiArray[iR1+1]; + }; + + uint32 nU0 = (iR1+umiArrayStride)/umiArrayStride;//number of UMIs after simple exact collapse + + if (pSolo.umiFiltering.MultiGeneUMI_CR) { + if (nU0==0) + continue; //nothing to count + + for (uint64 iu=0; iu0, false, umiCorrected[iG]); + + for (uint64 iu=0; iu0) {//otherwise no need to count + if (pSolo.umiDedup.yes.Exact) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.Exact] = nU0; + + if (pSolo.umiDedup.yes.CR) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.CR] = + umiArrayCorrect_CR(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::CR, true, umiCorrected[iG]); + + if (pSolo.umiDedup.yes.Directional) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.Directional] = + umiArrayCorrect_Directional(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::Directional, true, umiCorrected[iG], 0); + + if (pSolo.umiDedup.yes.Directional_UMItools) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.Directional_UMItools] = + umiArrayCorrect_Directional(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::Directional_UMItools, true, umiCorrected[iG], -1); + + //this changes umiArray, so it should be last call + if (pSolo.umiDedup.yes.All) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.All] = + umiArrayCorrect_Graph(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::All, true, umiCorrected[iG]); + };//if (nU0>0) + + {//check any count>0 and finalize record for this gene + uint32 totcount=0; + for (uint32 ii=countCellGeneUMIindex[iCB+1]+1; ii0) {//at least one umiDedup type is non-0 + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + 0] = gID[iG]; + nGenePerCB[iCB]++; + nUMIperCB[iCB] += countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.main]; + countCellGeneUMIindex[iCB+1] = countCellGeneUMIindex[iCB+1] + countMatStride;//iCB+1 accumulates the index + }; + }; + + if (readInfo.size()>0) {//record cb/umi for each read + for (uint32 iR=0; iR0) + umi=umiCorrected[iG][umi]; //correct UMI + readInfo[iread1].umi=umi; + }; + }; + }; + + if (pSolo.umiFiltering.MultiGeneUMI_CR) { + + vector geneCounts(nGenes,0); + + vector> geneUmiHash; + if (readInfo.size()>0) + geneUmiHash.resize(nGenes); + + for (auto &iu: umiGeneHash) {//loop over UMIs for all genes + + uint32 maxu=0, maxg=-1; + for (auto &ig : iu.second) { + if (ig.second>maxu) { + maxu=ig.second; + maxg=ig.first; + } else if (ig.second==maxu) { + maxg=-1; + }; + }; + + if ( maxg+1==0 ) + continue; //this umi is not counted for any gene, because two genes have the same read count for this UMI + + for (auto &ig : umiGeneHash0[iu.first]) {//check that this umi/gene had also top count for uncorrected umis + if (ig.second>umiGeneHash0[iu.first][maxg]) { + maxg=-1; + break; + }; + }; + + if ( maxg+1!=0 ) {//this UMI is counted + geneCounts[maxg]++; + if (readInfo.size()>0) + geneUmiHash[maxg].insert(iu.first); + }; + }; + + for (uint32 ig=0; ig0) {//record cb/umi for each read + for (uint32 iG=0; iG0) + umi=umiCorrected[iG][umi]; //correct UMI + + //cout << iG << "-" << iR << " " <0) { + readInfo[iread1].umi=umi; + } else { + readInfo[iread1].umi=(uintUMI) -1; + }; + }; + }; + }; + }; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////// +uint32 SoloFeature::umiArrayCorrect_CR(const uint32 nU0, uintUMI *umiArr, const bool readInfoRec, const bool nUMIyes, unordered_map &umiCorr) +{ + qsort(umiArr, nU0, umiArrayStride*sizeof(uint32), funCompareSolo1); + + for (uint64 iu=0; iuiu; iuu-=umiArrayStride) { + + uint32 uuXor = umiArr[iu+0] ^ umiArr[iuu+0]; + + if ( (uuXor >> (__builtin_ctz(uuXor)/2)*2) <= 3 ) {//1MM + umiArr[iu+2]=umiArr[iuu+0];//replace iu with iuu + break; + }; + }; + }; + + if (readInfoRec) {//record corrections + for (uint64 iu=0; iu umiC; + for (uint64 iu=0; iu &umiCorr, const int32 dirCountAdd) +{ + qsort(umiArr, nU0, umiArrayStride*sizeof(uint32), funCompareNumbersReverseShift);//TODO no need to sort by sequence here, only by count. + + for (uint64 iu=0; iu> (__builtin_ctz(uuXor)/2)*2) <= 3 && umiArr[iuu+1] >= (2*umiArr[iu+1]+dirCountAdd) ) {//1MM && directional condition + umiArr[iu+2]=umiArr[iuu+2];//replace iuu with iu-corrected + nU1--; + break; + }; + }; + }; + + if (readInfoRec) {//record corrections + for (uint64 iu=0; iu umiC; + for (uint64 iu=0; iu +#include "SoloCommon.h" + +inline int funCompareSolo1 (const void *a, const void *b); //defined below +inline int funCompare_uint32_1_2_0 (const void *a, const void *b); + +void SoloFeature::collapseUMIall(uint32 iCB, uint32 *umiArray) +{ + + uint32 *rGU=rCBp[iCB]; + uint32 rN=nReadPerCB[iCB]; //with multimappers, this is the number of all aligns, not reads + + qsort(rGU,rN,rguStride*sizeof(uint32),funCompareNumbers); //sort by gene index + + uint32 gid1 = -1;//current gID + uint32 nGenes = 0, nGenesMult = 0; //number of genes + uint32 *gID = new uint32[min(featuresNumber,rN)+1]; //gene IDs + uint32 *gReadS = new uint32[min(featuresNumber,rN)+1]; //start of gene reads TODO: allocate this array in the 2nd half of rGU + for (uint32 iR=0; iR=geneMultMark) + ++nGenesMult; + }; + }; + gReadS[nGenes]=rguStride*rN;//so that gReadS[nGenes]-gReadS[nGenes-1] is the number of reads for nGenes, see below in qsort + nGenes -= nGenesMult;//unique only gene + nReadPerCBunique[iCB] = gReadS[nGenes]/rguStride; //number of unique reads for this CB + nReadPerCBtotal[iCB] = nReadPerCBunique[iCB]; + + //unordered_map > umiGeneMap; + unordered_map > umiGeneMapCount, umiGeneMapCount0; + //UMI //Gene //Count + if (pSolo.umiFiltering.MultiGeneUMI) { + for (uint32 iR=0; iRig.second) + ig.second=0; //kills Gene with read count *strictly* < maximum count + }; + }; + }; + + if (pSolo.umiFiltering.MultiGeneUMI_All) { + for (uint32 iR=0; iR1) { + for (auto &ig : iu.second) + ig.second=0; //kill all genes for this UMI + }; + }; + }; + + vector> umiCorrected(nGenes); + + if (countCellGeneUMI.size() < countCellGeneUMIindex[iCB] + nGenes*countMatStride) + countCellGeneUMI.resize((countCellGeneUMI.size() + nGenes*countMatStride )*2);//allocated vector too small + + nGenePerCB[iCB]=0; + nUMIperCB[iCB]=0; + countCellGeneUMIindex[iCB+1]=countCellGeneUMIindex[iCB]; + + ///////////////////////////////////////////// + /////////// main cycle over genes with unique-gene-mappers + for (uint32 iG=0; iG); + + //exact collapse + uint32 iR1=-umiArrayStride; //number of distinct UMIs for this gene + uint32 u1=-1; + for (uint32 iR=rguU; iRnRumiMax) nRumiMax=umiArray[iR1+1]; + }; + + uint32 nU0 = (iR1+umiArrayStride)/umiArrayStride;//number of UMIs after simple exact collapse + + if (pSolo.umiFiltering.MultiGeneUMI_CR) { + if (nU0==0) + continue; //nothing to count + + for (uint64 iu=0; iu0, false, umiCorrected[iG]); + + for (uint64 iu=0; iu0) {//otherwise no need to count + if (pSolo.umiDedup.yes.Exact) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.Exact] = nU0; + + if (pSolo.umiDedup.yes.CR) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.CR] = + umiArrayCorrect_CR(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::CR, true, umiCorrected[iG]); + + if (pSolo.umiDedup.yes.Directional) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.Directional] = + umiArrayCorrect_Directional(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::Directional, true, umiCorrected[iG], 0); + + if (pSolo.umiDedup.yes.Directional_UMItools) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.Directional_UMItools] = + umiArrayCorrect_Directional(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::Directional_UMItools, true, umiCorrected[iG], -1); + + //this changes umiArray, so it should be last call + if (pSolo.umiDedup.yes.All) + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.All] = + umiArrayCorrect_Graph(nU0, umiArray, readInfo.size()>0 && pSolo.umiDedup.typeMain==UMIdedup::typeI::All, true, umiCorrected[iG]); + };//if (nU0>0) + + {//check any count>0 and finalize record for this gene + uint32 totcount=0; + for (uint32 ii=countCellGeneUMIindex[iCB+1]+1; ii0) {//at least one umiDedup type is non-0 + countCellGeneUMI[countCellGeneUMIindex[iCB+1] + 0] = gID[iG]; + nGenePerCB[iCB]++; + nUMIperCB[iCB] += countCellGeneUMI[countCellGeneUMIindex[iCB+1] + pSolo.umiDedup.countInd.main]; + countCellGeneUMIindex[iCB+1] = countCellGeneUMIindex[iCB+1] + countMatStride;//iCB+1 accumulates the index + }; + }; + + if (readInfo.size()>0) {//record cb/umi for each read + for (uint32 iR=0; iR0) + umi=umiCorrected[iG][umi]; //correct UMI + readInfo[iread1].umi=umi; + }; + }; + }; + + if (pSolo.umiFiltering.MultiGeneUMI_CR) { + + vector geneCounts(nGenes,0); + + vector> geneUmiHash; + if (readInfo.size()>0) + geneUmiHash.resize(nGenes); + + for (const auto &iu: umiGeneMapCount) {//loop over UMIs for all genes + + uint32 maxu=0, maxg=-1; + for (const auto &ig : iu.second) { + if (ig.second>maxu) { + maxu=ig.second; + maxg=ig.first; + } else if (ig.second==maxu) { + maxg=-1; + }; + }; + + if ( maxg+1==0 ) + continue; //this umi is not counted for any gene, because two genes have the same read count for this UMI + + for (const auto &ig : umiGeneMapCount0[iu.first]) {//check that this umi/gene had also top count for uncorrected umis + if (ig.second>umiGeneMapCount0[iu.first][maxg]) { + maxg=-1; + break; + }; + }; + + if ( maxg+1!=0 ) {//this UMI is counted + geneCounts[maxg]++; + if (readInfo.size()>0) + geneUmiHash[maxg].insert(iu.first); + }; + }; + + for (uint32 ig=0; ig0) {//record cb/umi for each read + for (uint32 iG=0; iG0) + umi=umiCorrected[iG][umi]; //correct UMI + + //cout << iG << "-" << iR << " " <0) { + readInfo[iread1].umi=umi; + } else { + readInfo[iread1].umi=(uintUMI) -1; + }; + }; + }; + }; + }; + + //////////////////////////////////////////multi-gene reads + ////////////////////////////////////////// + if (pSolo.multiMap.yes.multi) + countMatMult.i[iCB+1] = countMatMult.i[iCB]; + + if (nGenesMult>0) {//process multigene reads + + if (readInfo.size()>0) { + for (uint32 iR=gReadS[nGenes]; iR> umiGenes; + umiGenes.reserve(256); + {//for each umi, count number of reads per gene. + //Output umiGenes: only genes with nReads = nReads-for-this-UMI will be kept for this UMI + uint32 *rGUm = rGU + gReadS[nGenes]; + uint32 nRm=( gReadS[nGenes+nGenesMult] - gReadS[nGenes] ) / rguStride; + + //sort by UMI, then by read, then by gene + qsort(rGUm, nRm, rguStride*sizeof(uint32), funCompare_uint32_1_2_0);//there is no need to sort by read or gene actually + + std::unordered_map geneReadCount; //number of reads per gene + uint32 nRumi=0; + bool skipUMI=false; + uintUMI umiPrev = (uintUMI)-1; + uintRead readPrev = (uintRead)-1; + for (uint32 iR=0; iR0) { + skipUMI = true;//this UMI is skipped because it was among uniquely mapped + } else { + skipUMI = false;//new good umi + geneReadCount.clear(); + nRumi=0; + readPrev = (uintRead)-1; + }; + }; + + if (skipUMI) + continue; //this UMI is skipped because it was among uniquely mapped + + uintRead read1 = rGUm[iR+2]; + if (read1 != readPrev) { + ++nRumi; + readPrev = read1; + nReadPerCBtotal[iCB]++; + }; + + uint32 g1 = rGUm[iR+0] ^ geneMultMark; //XOR to unset the geneMultMark bit + geneReadCount[g1]++; + + if (iR == nRm*rguStride-rguStride || umi1 != rGUm[iR+1+rguStride]) {//record this umi + uint32 ng=0; + for (const auto &gg: geneReadCount) { + if (gg.second == nRumi) + ++ng; + }; + vector vg; + vg.reserve(ng);//this and above is to construct vector of precise size, for efficiency? + for (const auto &gg: geneReadCount) { + if (gg.second == nRumi) + vg.push_back(gg.first); + }; + umiGenes.push_back(vg); + }; + }; + }; + + std::map genesM; //genes to quantify + + {//collect all genes, replace geneID with index in umiGenes + uint32 ng = 0; + for (auto &uu: umiGenes) { + for (auto &gg: uu) { + if (genesM.count(gg) == 0) {//new gene + genesM[gg]=ng; + ++ng; + }; + gg = genesM[gg]; + }; + }; + }; + + + vector gEuniform(genesM.size(), 0); + {//gEuniform=uniformly distribute multigene UMIs + for (auto &ug: umiGenes) { + for (auto &gg: ug) { + gEuniform[gg] += 1.0 / double(ug.size()); // 1/n_genes_umi + }; + }; + }; + + vector> gErescue(pSolo.umiDedup.yes.N); + if (pSolo.multiMap.yes.Rescue) { + + for (uint32 indDedup=0; indDedup < pSolo.umiDedup.yes.N; indDedup++) { + vector gEu(genesM.size(), 0); + {//collect unique gene counts + for (uint32 igm=countCellGeneUMIindex[iCB]; igm0) + gEu[genesM[g1]]=(double)countCellGeneUMI[igm+1+indDedup]; + }; + }; + + gErescue[indDedup].resize(genesM.size(), 0); + {//gErescue=distribute UMI proportionally to gEuniform+gEu + for (auto &ug: umiGenes) { + double norm1 = 0.0; + for (auto &gg: ug) + norm1 += gEuniform[gg]+gEu[gg]; + + if (norm1==0.0) + continue; //this should not happen since gEuniform is non-zero for all genes involved + norm1 = 1.0 / norm1; + + for (auto &gg: ug) { + gErescue[indDedup][gg] += (gEuniform[gg]+gEu[gg])*norm1; + }; + }; + }; + }; + }; + + vector> gEpropUnique(pSolo.umiDedup.yes.N); + if (pSolo.multiMap.yes.PropUnique) { + + for (uint32 indDedup=0; indDedup < pSolo.umiDedup.yes.N; indDedup++) { + vector gEu(genesM.size(), 0); + {//collect unique gene counts + for (uint32 igm=countCellGeneUMIindex[iCB]; igm0) + gEu[genesM[g1]]=(double)countCellGeneUMI[igm+1+indDedup]; + }; + }; + + gEpropUnique[indDedup].resize(genesM.size(), 0); + {//gErescue=distribute UMI proportionally to gEuniform+gEu + for (auto &ug: umiGenes) { + double norm1 = 0.0; + for (auto &gg: ug) + norm1 += gEu[gg]; + + if (norm1==0.0) {//this UMI has no genes with unique mappers - distribute it uniformly + for (auto &gg: ug) + gEpropUnique[indDedup][gg] += 1.0 / double(ug.size()); + } else {//this UMI has genes with unique mappers - distribute it proportionally to unique mappers + norm1 = 1.0 / norm1; + for (auto &gg: ug) + gEpropUnique[indDedup][gg] += gEu[gg]*norm1; + }; + }; + }; + }; + }; + + vector> gEem(pSolo.umiDedup.yes.N); + if (pSolo.multiMap.yes.EM) { + + for (uint32 indDedup=0; indDedup < pSolo.umiDedup.yes.N; indDedup++) { + vector gEu(genesM.size(), 0); + {//collect unique gene counts + for (uint32 igm=countCellGeneUMIindex[iCB]; igm0) + gEu[genesM[g1]]=(double)countCellGeneUMI[igm+1+indDedup]; + }; + }; + + {//gEem = EM + + vector gEM1 = gEuniform; + for (uint32 ii=0; ii gEM2(genesM.size(), 0); + + auto *gEM1p=&gEM1; + auto *gEM2p=&gEM2; + + double maxAbsChange=1; + uint32 iterI=0; + while(true) { + ++iterI; + + auto &gEMold=*gEM1p; //for convenience - to use instead of pointer + auto &gEMnew=*gEM2p; + + std::copy(gEu.begin(), gEu.end(), gEMnew.begin());//gEMnew is initialized with unique counts + + for (auto &gg: gEMold) {//zero-out very small counts + if (gg<0.01) //hardcoded + gg=0; + }; + + for (auto &ug: umiGenes) { + double norm1 = 0.0; + for (auto &gg: ug) //cycle over genes for this umi + norm1 += gEMold[gg]; + + norm1 = 1.0 / norm1; + + for (auto &gg: ug) { + gEMnew[gg] += gEMold[gg]*norm1; + }; + }; + + maxAbsChange=0.0; + for (uint32 ii=0; ii maxAbsChange) + maxAbsChange = change1; + }; + + if (maxAbsChange < 0.01 || iterI>100) {//hardcoded + gEem[indDedup] = gEMnew; + break; + }; + + swap(gEM1p, gEM2p); //swap new and old for the next interation of EM + }; + + for (uint32 ii=0; iivb[1]) { + return 1; + } else if (va[1]vb[0]){ + return 1; + } else if (va[0]vb[1]) { + return 1; + } else if (va[1]vb[2]){ + return 1; + } else if (va[2]vb[0]){ + return 1; + } else if (va[0] &umiCorr) +{ + qsort(umiArr, nU0, umiArrayStride*sizeof(uint32), funCompareSolo1); + + for (uint64 iu=0; iuiu; iuu-=umiArrayStride) { + + uint32 uuXor = umiArr[iu+0] ^ umiArr[iuu+0]; + + if ( (uuXor >> (__builtin_ctz(uuXor)/2)*2) <= 3 ) {//1MM + umiArr[iu+2]=umiArr[iuu+0];//replace iu with iuu + break; + }; + }; + }; + + if (readInfoRec) {//record corrections + for (uint64 iu=0; iu umiC; + for (uint64 iu=0; iu &umiCorr, const int32 dirCountAdd) +{ + qsort(umiArr, nU0, umiArrayStride*sizeof(uint32), funCompareNumbersReverseShift);//TODO no need to sort by sequence here, only by count. + + for (uint64 iu=0; iu> (__builtin_ctz(uuXor)/2)*2) <= 3 && umiArr[iuu+1] >= (2*umiArr[iu+1]+dirCountAdd) ) {//1MM && directional condition + umiArr[iu+2]=umiArr[iuu+2];//replace iuu with iu-corrected + nU1--; + break; + }; + }; + }; + + if (readInfoRec) {//record corrections + for (uint64 iu=0; iu umiC; + for (uint64 iu=0; iulogMain << timeMonthDayTime(rawTime) << " ... Allocated and initialized readInfo array, nReadsInput = " << nReadsInput <cbReadCount[ii]>0) { + rCBp[nCB+1] = rCBp[nCB] + rguStride*readFeatSum->cbReadCount[ii]; + ++nCB; + }; + rCBpa[ii+1]=rCBp[nCB]; + }; + + //read and store the CB/gene/UMI from files + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished allocating arrays for Solo " << nReadsMapped*rguStride*4.0/1024/1024/1024 <<" GB" <inputRecords(rCBpa, rguStride, readBarSum->cbReadCountExact, readInfo); + }; + + nReadPerCB.resize(nCB); + uint32 nReadPerCBmax=0; + for (uint32 iCB=0; iCBstats.V[readFeatSum->stats.yesWLmatch] += nReadPerCB[iCB]; + }; + + for (int ii=0; iiaddStats(*readFeatAll[ii]); + }; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished reading reads from Solo files nCB="<addStats(*readFeatAll[ii]); + }; + + redistributeReadsByCB(); + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) <<" ... Finished redistribution of reads from Solo read files"<> vCellFeatureCount(nCB); + + typedef struct { + uint32 feature; + uint64 umi; + } typeFeatureUMI; + vector::iterator> cbFeatUMI (nCB + 1); + + #pragma omp parallel for num_threads(P.runThreadN) + for (uint32 ired=0; ired vFeatureUMI (redistrFilesNreads[ired]); + + uint32 iCB1=redistrFilesCBfirst[ired]; + uint32 iCB2=redistrFilesCBfirst[ired+1]; + + //allocate arrays + cbFeatUMI[iCB1]=vFeatureUMI.begin(); + for (uint32 icb=iCB1+1; icbcbReadCount[indCB[icb-1]]; + }; + + //input records + redistrFilesStreams[ired]->flush(); + redistrFilesStreams[ired]->seekg(0,ios::beg); + + uint32 feature; + uint64 umi, iread; + int32 cbmatch; + int64 cb; + vector trIdDist; //not used + bool readInfoYes=false; + while (soloInputFeatureUMI(redistrFilesStreams[ired], featureType, readInfoYes, P.sjAll, iread, cbmatch, feature, umi, trIdDist)) {//cycle over file records + + *redistrFilesStreams[ired] >> cb; + + if (feature+1 == 0) + continue; + + uint32 icb=indCBwl[cb]; + *( cbFeatUMI[icb] + nReadPerCB[icb] )={feature,umi}; + nReadPerCB[icb]++; + }; + + //collapse UMI, simple + for (uint32 icb=iCB1; icbfeature, {1,1}});//first read + for (auto fu=cbFeatUMI[icb]+1; fu!=cbFeatUMI[icb]+nReadPerCB[icb]; fu++) {//cycle over all reads for this icb + if ( fu->feature != (fu-1)->feature ) {//compare to previous feature + vCellFeatureCount[icb].push_back({fu->feature, {1,1}});//create next feature entry + } else {//same feature + vCellFeatureCount[icb].back().count[0]++; //non-collapsed UMI count + + if ( fu->umi != (fu-1)->umi ) {//same feature, new umi + vCellFeatureCount[icb].back().count[1]++;//collapsed UMI count + }; + }; + }; + }; + }; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished reading / collapsing" <stats.V[readFeatSum->stats.yesWLmatch] += nReadPerCBtotal[icb]; + readFeatSum->stats.V[readFeatSum->stats.yesWLmatch_UniqueFeature] += nReadPerCBunique[icb]; + + readFeatSum->stats.V[readFeatSum->stats.yesUMIs] += nUMIperCB[icb]; + if (nGenePerCB[icb]>0) + ++readFeatSum->stats.V[readFeatSum->stats.yesCellBarcodes]; + }; + + readFeatSum->stats.V[readFeatSum->stats.yessubWLmatchExact]=readFeatSum->stats.V[readFeatSum->stats.yesWLmatch]; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished SmartSeq counting" < +#include + +void SoloFeature::countVelocyto() +{//velocyto counting gets info from Gene counting + time_t rawTime; + + nReadPerCB.resize(nCB); + + vector>> cuTrTypes (nCB); + for (uint32 ii=0; iicbReadCount[ii] > 100 ? readFeatSum->cbReadCount[ii] : readFeatSum->cbReadCount[ii]/5); //heuristics... + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Velocyto counting: allocated arrays" <streamReads; + streamReads->flush(); + streamReads->seekg(0,ios::beg); + + uint64 iread; + while (*streamReads >> iread) {//until the end of file + uintCB cb=soloFeatAll[pSolo.featureInd[SoloFeatureTypes::Gene]]->readInfo[iread].cb; + uintUMI umi=soloFeatAll[pSolo.featureInd[SoloFeatureTypes::Gene]]->readInfo[iread].umi; + if (cb == (uintCB)-1 || umi == (uintUMI)-1 ) {//CB and/or UMI undefined. TODO: put a filter on CBs here, e.g. UMI threshold + streamReads->ignore((uint32)-1, '\n'); + continue; + }; + + uint32 iCB=indCBwl[cb]; + nReadPerCB[iCB]++;//simple estimate + + if (cuTrTypes[iCB].count(umi)>0 && cuTrTypes[iCB][umi].empty()) {//intersection is empty, no need to load this transcript + streamReads->ignore((uint32)-1, '\n'); + continue; + }; + + uint32 nTr; + *streamReads >> nTr; + vector trT(nTr); + for (auto & tt: trT) { + uint32 ty; + *streamReads >> tt.tr >> ty; + tt.type=(uint8) ty; + }; + + if (cuTrTypes[iCB].count(umi)==0) {//1st entry for this umi + cuTrTypes[iCB][umi]=trT; + continue; + }; + + uint32 inew=0; + vector trT1; + trT1.reserve(cuTrTypes[iCB][umi].size()); + + for (uint32 iold=0; ioldtrT[inew].tr) //move through the sorted lists + ++inew; + + if (inew == trT.size() ) //end of trT reached + break; + + if (cuTrTypes[iCB][umi][iold].tr == trT[inew].tr) {// + trT1.push_back({trT[inew].tr, (uint8)(cuTrTypes[iCB][umi][iold].type | trT[inew].type)}); + }; + }; + cuTrTypes[iCB][umi]=trT1;//replace with intersection + }; + }; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Velocyto counting: finished input" <> geneC; + for (auto &umi : cuTrTypes[iCB]) {//cycle over UMIs + if (umi.second.empty()) //no transcripts in the intesect + continue; + uint32 geneI=Trans.trGene[umi.second[0].tr]; + + //for each transcript, are all UMIs: + bool exonModel=false; //purely exonic + bool intronModel=false; //purely intronic + bool spanModel=true; //spanning model for all UMIs + bool mixedModel=false; //both intronic and exonic, but not spanning + + for (auto &tt : umi.second) {//cycle over transcripts in this UMI + if (Trans.trGene[tt.tr] != geneI) {//multigene + geneI=(uint32)-1; + break; + }; + + bitset gV (tt.type); + + mixedModel |= ((gV.test(AlignVsTranscript::Intron) && gV.test(AlignVsTranscript::Concordant)) || gV.test(AlignVsTranscript::ExonIntron)) && !gV.test(AlignVsTranscript::ExonIntronSpan);//has exon and intron, but no span + spanModel &= gV.test(AlignVsTranscript::ExonIntronSpan); + exonModel |= gV.test(AlignVsTranscript::Concordant) && !gV.test(AlignVsTranscript::Intron) && !gV.test(AlignVsTranscript::ExonIntron);//has only-exons model + intronModel |= gV.test(AlignVsTranscript::Intron) && !gV.test(AlignVsTranscript::ExonIntron) && !gV.test(AlignVsTranscript::Concordant);//has only-introns model, this includes span + }; + + if (geneI+1==0) //multigene + continue; + + if (exonModel && !intronModel && !mixedModel) {// all models are only-exons + geneC[geneI][0]++; //spliced + } else if ( spanModel || + ( (intronModel || mixedModel) && !exonModel) + ) {//all models are only-spans. Not sure if this ever happens, should be simplified. Intron or mixed, but not exon + geneC[geneI][1]++;//unspliced + } else {//all other combinations are mixed models, i.e. both only-exons and only-introns, only-exons and mixed + geneC[geneI][2]++;//ambiguous + }; + + nUMIperCB[iCB]++; + }; + + countCellGeneUMIindex[iCB+1] = countCellGeneUMIindex[iCB]; + + if (nUMIperCB[iCB]==0) //no UMIs counted for this CB + continue; + + nGenePerCB[iCB]+=geneC.size(); + readFeatSum->stats.V[readFeatSum->stats.yesUMIs] += nUMIperCB[iCB]; + ++readFeatSum->stats.V[readFeatSum->stats.yesCellBarcodes]; + + if (countCellGeneUMI.size() < countCellGeneUMIindex[iCB+1] + geneC.size()*countMatStride) //allocated vector too small + countCellGeneUMI.resize(countCellGeneUMI.size()*2); + + for (auto & gg : geneC) { + countCellGeneUMI[countCellGeneUMIindex[iCB+1]+0]=gg.first; + for (uint32 ii=0;ii<3;ii++) + countCellGeneUMI[countCellGeneUMIindex[iCB+1]+1+ii]=gg.second[ii]; + countCellGeneUMIindex[iCB+1] += countMatStride; + }; + }; + + //for now only unique mappers are considered for velocyto + nReadPerCBtotal = nReadPerCB; + nReadPerCBunique = nReadPerCB; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Velocyto counting: finished collapsing UMIs" < +#include +#include +#include + +double logMultinomialPDFsparse(const vector &ambProfileLogP, const vector &countCellGeneUMI, const uint32 stride, const uint32 shift, const int64 start, const uint32 nGenes, const vector &logFactorial); +void SoloFeature::emptyDrops_CR() +{ + if (nCB<=pSolo.cellFilter.eDcr.indMin) { + P.inOut->logMain << "emptyDrops_CR filtering: total number of cells: nCB=" << nCB <<" is smaller than emptyCellMinIndex="<< pSolo.cellFilter.eDcr.indMin + << ", which is the starting index for the *true empty* cells. The additional non-empty cells will not be detected.\n"; + return; + }; + + time_t rawTime; + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) <<" ... starting emptyDrops_CR filtering" < featDet; + for (uint32 icb=0; icb 0) + featDet.insert(countCellGeneUMI[irec]); //gene is present if it's count > 0 for + }; + }; + uint32 featDetN=featDet.size(); //total number of detected genes - this should have been done already? + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //indCount - total UMI per cell sorted descending + typedef struct {uint32 index, count;} IndCount; + vector indCount(nCB); + for (uint32 ii=0; iiic2.count) || (ic1.count==ic2.count && ic1.index ambCount(featuresNumber,0); + for (auto icb=pSolo.cellFilter.eDcr.indMin; icblogMain << timeMonthDayTime(rawTime) <<" ... finished ambient cells counting" < ambCountFreq; //ordered map is not really needed + for (auto &ac: ambCount) { + ambCountFreq[ac]++; + }; + if (ambCountFreq.size()<=1) {//only 0-frequency genes are in the empty cells. This is possible because nCB can contain ome cells with no genes - because of multigene + P.inOut->logMain << "emptyDrops_CR filtering: empty cells contain no genes\n"; + return; + }; + ambCountFreq[0] -= (featuresNumber-featDetN); //subtract genes that were not detected in *any* cells + uint32 maxFreq = ambCountFreq.rbegin()->first; + + /////////////////////////////////////////////////////////////////////// + //SGT + vector ambCountFreqSGT(maxFreq+1);//up to max frequency + {//SGT estimate of ambient profile + SGT sgt; + for (auto &cf: ambCountFreq) { + if (cf.first != 0) + sgt.add(cf.first, cf.second); + }; + sgt.analyse(); + + for (uint32 freq=0; freq<=maxFreq; freq++) { + sgt.estimate(freq, ambCountFreqSGT[freq]); + }; + ambCountFreqSGT[0] /= ambCountFreq[0]; //divide freq=0 probability equally among all undetected genes in ambient profile + }; + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) <<" ... finished SGT"< ambProfileLogP(featuresNumber, 0.0);//logarithm + vector ambProfilePnon0, ambProfileLogPnon0;//only non-0 genes + { + for (uint32 ig=0; ig0) {//this is only needed if normalization below is performed + ambProfileLogP[ig]=ambCountFreqSGT[ambCount[ig]]; + }; + }; + + double norm1 = accumulate(ambProfileLogP.begin(), ambProfileLogP.end(), 0.0); + ambProfileLogPnon0.reserve(ambProfileLogP.size()); + ambProfilePnon0.reserve(ambProfileLogP.size()); + for (auto &cf: ambProfileLogP) { + if (cf>0) { + cf /= norm1;//normalization is just in case + ambProfilePnon0.push_back(cf); + cf = std::log(cf); + ambProfileLogPnon0.push_back(cf); + }; + }; + }; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) <<" ... finished ambient profile"<logMain << timeMonthDayTime(rawTime) << " ... candidate cells: minUMI="<< minUMI << "; number of candidate cells=" << iCandLast-iCandFirst+1 < obsLogProb(iCandLast-iCandFirst+1); + { + vector logFactorial; //tabulate log-factorial + logFactorial.resize(indCount[iCandFirst].count+1); + logFactorial[1]=0; + for (uint32 cc=2; cclogMain << timeMonthDayTime(rawTime) << " ... finished observed logProb" <> simLogProb(pSolo.cellFilter.eDcr.simN); + { + std::discrete_distribution distrAmb ( ambProfilePnon0.begin(), ambProfilePnon0.end() ); + auto maxCount=indCount[iCandFirst].count; + + //#pragma omp parallel for num_threads(P.runThreadN) //does not increase speed significantly - might be useful for larger number of simulations + for (uint64 isim=0; isim currCounts(ambProfilePnon0.size(), 0); + for (uint32 ic=1; ic<=maxCount; ic++) { + uint32 ig1 = distrAmb(rngGen); + currCounts[ig1]++; + simLogProb[isim][ic] = simLogProb[isim][ic-1] + ambProfileLogPnon0[ig1] + std::log(ic) - std::log(currCounts[ig1]); + }; + }; + }; + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... finished simulations" < pValues(obsLogProb.size()); + { + for (uint32 icand=0; icand sp) { return n + (sp[count1](simLogProb.begin(), simLogProb.end(), 0, funSumLess); + uint32 nLowerP=0; + //for (uint64 isim=0; isimpadj = min(ip->padj, (ip-1)->padj); //make it non-decreasing + }; + + uint32 extraCells=0; + for (auto &ip: pValues) { + if (ip.padj<=pSolo.cellFilter.eDcr.FDR) { + ++extraCells; + filteredCells.filtVecBool[ip.index]=true; + }; + }; + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... finished emptyDrops_CR filtering: number of additional non-ambient cells=" << extraCells < &ambProfileLogP, const vector &countCellGeneUMI, const uint32 stride, const uint32 shift, const int64 start, const uint32 nGenes, const vector &logFactorial) +{ + uint32 sumCount=0; + double sumLogFac=0.0, sumCountLogP=0.0; + for (uint32 ig=0; iglogMain, EXIT_CODE_PARAMETER, P); + }; + + string inputPrefix= P.runModeIn[1] + '/'; + outputPrefix= P.runModeIn[2]; + outputPrefixFiltered= outputPrefix; + + ///////////////////////////////////////////////////////////// + //load counting matrix + string matrixFileName=inputPrefix+pSolo.outFileNames[3]; + ifstream &matStream=ifstrOpen(matrixFileName, ERROR_OUT, "SOLUTION: check path and permission for the matrix file" + matrixFileName, P); + + //header + while (matStream.peek() == '%') { + string dummy; + matStream.ignore(numeric_limits::max(), '\n'); + }; + + uint32 nCB1; //number of features read from file + uint64 nTot; //total number of entries + matStream >> featuresNumber >> nCB1 >> nTot; + + if (nTot==0) { + exitWithError("Exiting because of fatal INPUT FILE error: no counts detected in " + matrixFileName + \ + "\nSOLUTION: check the formatting of the matrix file.\n", \ + std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); + }; + + /* do not need it - read the information from features file + if (nfeat1 != featuresNumber) { + ostringstream errOut; + errOut <<"Exiting because of fatal INPUT FILE error: number of features in "<< matrixFileName <<": "<< nfeat1; + errOut <<"\n is not equal to the number of features from annotations from genome index: " << featuresNumber << "\n"; + errOut <<"SOLUTION: use the same genome index that was use in the STARsolo run that generated the matrix\n"; + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); + }; + */ + + //struct {uint32 gene; uint32 cb; uint32 count} matEntry; + /*vector> matSparse(nTot); + for (uint64 ii=0; ii> matSparse[ii][jj]; + }; + + //sort by cell index + std::sort(matSparse.begin(), matSparse.end(), [](const array &m1, const array &m2) { + return m1[1] < m2[1] ; + }); + */ + + countMatStride=3; //gene, cell, count. Recording cell at shift=1 is temporary: later will replace cell with count + countCellGeneUMI.resize(nTot*countMatStride,0); + + //countMatMult.s = 3; + //countMatMult.m.resize(nTot*countMatStride,0.0); + + for (uint64 ii=0; ii> countCellGeneUMI[ii*countMatStride+0];//gene + --countCellGeneUMI[ii*countMatStride+0]; //0-based gene + + matStream >> countCellGeneUMI[ii*countMatStride+1];//cell + --countCellGeneUMI[ii*countMatStride+1]; //0-based cell + + double count1; + matStream >> count1; + countCellGeneUMI[ii*countMatStride+2] = std::round(count1); + + /* to keep fractional part + matStream >> countMatMult.m[ii*countMatStride+2];//count: for now, only allow one value per cell/gene + countCellGeneUMI[ii*countMatStride+2] = std::round(countMatMult.m[ii*countMatStride+2]); //round to integer + countMatMult.m[ii*countMatStride+2] -= countCellGeneUMI[ii*countMatStride+2]; //just the fractional part + countMatMult.m[ii*countMatStride+0] = countCellGeneUMI[ii*countMatStride+0]; + countMatMult.m[ii*countMatStride+1] = countCellGeneUMI[ii*countMatStride+1]; + */ + }; + + qsort((void*) countCellGeneUMI.data(), nTot, countMatStride*sizeof(countCellGeneUMI[0]), funCompareTypeSecondFirst); + + + //count number of detected cell + nCB=0; + uint32 ciprev=(uint32) -1; + for (uint32 ii=0; iilogMain, EXIT_CODE_PARAMETER, P); }; - if (featureType==0 || !pSolo.featureYes[0]) { - //output CBs - ofstream &cbStr=ofstrOpen(P.outFileNamePrefix+pSolo.outFileNames[0]+pSolo.outFileNames[2],ERROR_OUT, P); - for (auto const &cb : pSolo.cbWL) - cbStr << convertNuclInt64toString(cb,pSolo.cbL) <<'\n'; - cbStr.flush(); + */ + + ///////////////////////////////////////////////////////////// + //write features.tsv + switch (featureType) { + case SoloFeatureTypes::Gene : + case SoloFeatureTypes::GeneFull : + case SoloFeatureTypes::GeneFull_Ex50pAS : + case SoloFeatureTypes::GeneFull_ExonOverIntron : + case SoloFeatureTypes::Velocyto : + case SoloFeatureTypes::VelocytoSimple : + { + ofstream &geneStr=ofstrOpen(outputPrefixMat+pSolo.outFileNames[1],ERROR_OUT, P); + for (uint32 ii=0; iilogMain, EXIT_CODE_PARAMETER, P); + }; + + //////////////////////////////////////////////////////////////////////////// + //write barcodes.tsv + ofstream &cbStr=ofstrOpen(outputPrefixMat+pSolo.outFileNames[2],ERROR_OUT, P); + uint64 nCellGeneEntries=0;//total number of non-zero cell/gene combinations (entries in the output matrix) + if (cellFilterYes) {//filtered cells + for (uint32 icb=0; icb velonames = {"spliced.mtx", "unspliced.mtx", "ambiguous.mtx"}; + matrixFileName += velonames[iCol-1]; + + } else if (iCol>1 && cellFilterYes) { + break; //if cellFilterYes, only output first iCol, since filtering is only done for it + + } else if (pSolo.umiDedup.types.size()>1) { + matrixFileName += "umiDedup-" + pSolo.umiDedup.typeNames[pSolo.umiDedup.types[iCol-1]] + ".mtx"; + + } else { + matrixFileName += pSolo.outFileNames[3]; + }; + ofstream &countMatrixStream=ofstrOpen(matrixFileName,ERROR_OUT, P); + + //header + countMatrixStream <<"%%MatrixMarket matrix coordinate integer general\n"; + countMatrixStream <<"%\n"; + countMatrixStream << featuresNumber <<' '<< (cellFilterYes ? filteredCells.nCells : pSolo.cbWLsize) <<' '<< nCellGeneEntries << '\n'; + + uint32 cbInd1=0; + for (uint32 icb=0; icb1) { + matrixFileName += "_umiDedup-" + pSolo.umiDedup.typeNames[pSolo.umiDedup.types[iDed]]; + }; + matrixFileName += ".mtx"; + + uint32 mIndex = pSolo.multiMap.countInd.I[iMult] + iDed; + + //string matOutString; + //matOutString.reserve(100000000); + std::ostringstream matOutStringStream;//(matOutString); + + nCellGeneEntries = 0; + + uint32 cbInd1=0; + for (uint32 icb=0; icbg2) { + matOutStringStream << g2+1 <<' '<< cbInd1 <<' '<< c2 <<'\n'; + igm2 += countMatMult.s; + } else { + matOutStringStream << g1+1 <<' '<< cbInd1 <<' '<< c1+c2 <<'\n'; + igm1 += countMatStride; + igm2 += countMatMult.s; + }; + + ++nCellGeneEntries; + }; + }; + }; + //matOutStringStream.flush(); + + ofstream &countMatrixStream=ofstrOpen(matrixFileName, ERROR_OUT, P); + + //header + countMatrixStream <<"%%MatrixMarket matrix coordinate float general\n"; + countMatrixStream <<"%\n"; + countMatrixStream << featuresNumber <<' '<< pSolo.cbWLsize <<' '<< nCellGeneEntries << '\n'; + countMatrixStream << matOutStringStream.str(); - for (uint32 icb=0; icb1) {//3 counts recorded - count1[0] = rCBpp[1]; - count1[1] = rCBpp[2]; - count1[2] = rCBpp[3]; - rCBpp += 4; - } else {//1 recorded - rCBpp +=2; + countMatrixStream.close(); }; - for (uint32 ii=0; iiflush(); }; diff --git a/source/SoloFeature_processRecords.cpp b/source/SoloFeature_processRecords.cpp index c4ac1878..aba5e3d8 100755 --- a/source/SoloFeature_processRecords.cpp +++ b/source/SoloFeature_processRecords.cpp @@ -1,115 +1,80 @@ #include "SoloFeature.h" #include "streamFuns.h" #include "TimeFunctions.h" +#include "SequenceFuns.h" +#include "ErrorWarning.h" -void SoloFeature::processRecords(ReadAlignChunk **RAchunk) +void SoloFeature::processRecords() { if (pSolo.type==0) return; time_t rawTime; time(&rawTime); - P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Starting Solo post-map for " <RA->soloRead->readFeat[pSolo.featureInd[featureType]]; - readBarAll[ii]=RAchunk[ii]->RA->soloRead->readBar; - }; - - for (int ii=0; iiaddCounts(*readFeatAll[ii]); - readBarSum->addCounts(*readBarAll[ii]); - }; - - if (!pSolo.cbWLyes) {//now we can define WL and counts - pSolo.cbWL.resize(readFeatSum->cbReadCountMap.size()); - readFeatSum->cbReadCount = new uint32[pSolo.cbWL.size()]; - readBarSum->cbReadCountExact = new uint32[pSolo.cbWL.size()]; - - uint64 icb=0; - for (auto ii=readFeatSum->cbReadCountMap.cbegin(); ii!=readFeatSum->cbReadCountMap.cend(); ++ii) { - pSolo.cbWL[icb]=ii->first; - readFeatSum->cbReadCount[icb]=ii->second; - readBarSum->cbReadCountExact[icb]=ii->second; - ++icb; + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Starting Solo post-map for " <logMain, EXIT_CODE_PARAMETER, P); + }; + + //prepare for feature-specific counting: + if (featureType==SoloFeatureTypes::SJ && P.sjAll[0].empty()) { + ifstream &sjIn = ifstrOpen(P.outFileTmp+"SJ.start_gap.tsv", ERROR_OUT, "SOLUTION: re-run STAR", P); + P.sjAll[0].reserve(10000000); + P.sjAll[1].reserve(10000000); + uint64 start1, gap1; + while ( sjIn >> start1 >> gap1 ) { + P.sjAll[0].emplace_back(start1); + P.sjAll[1].emplace_back(gap1); }; + sjIn.close(); + P.inOut->logMain <<"Read splice junctions for Solo SJ feature: "<< P.sjAll[0].size() <cbReadCountExact[ii]>0) { - nCB++; - nReadsMapped += readFeatSum->cbReadCount[ii]; - }; - }; - - rGeneUMI = new uint32[2*nReadsMapped]; //big array for all CBs - each element is gene and UMI - rCBp = new uint32*[nCB+1]; - uint32 **rCBpa = new uint32*[pSolo.cbWL.size()+1]; - indCB = new uint32[nCB]; - - uint32 nReadPerCBmax=0; - rCBp[0]=rGeneUMI; - rCBpa[0]=rGeneUMI; - nCB=0;//will count it again below - for (uint32 ii=0; iicbReadCountExact[ii]>0) {//if no exact matches, this CB is not present - indCB[nCB]=ii; - rCBp[nCB+1] = rCBp[nCB] + 2*readFeatSum->cbReadCount[ii]; - ++nCB; + SoloFeature::sumThreads(); + + //call counting method + if (featureType==SoloFeatureTypes::Velocyto) { + countVelocyto(); + } else if (featureType==SoloFeatureTypes::Transcript3p) { + quantTranscript(); + return; + } else {//all others, standard processing + if (pSolo.type==pSolo.SoloTypes::SmartSeq) { + countSmartSeq(); + } else { + countCBgeneUMI(); }; - rCBpa[ii+1]=rCBp[nCB]; - }; - - //read and store the CB/gene/UMI from files - time(&rawTime); - P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished allocating arrays for Solo " << nReadsMapped*2.0*8/1024/1024/1024 <<" GB" <inputRecords(rCBpa,readBarSum->cbReadCountExact); }; + + if (!(pSolo.multiMap.yes.multi && (featureType==SoloFeatureTypes::Gene || featureType==SoloFeatureTypes::GeneFull))) + readFeatSum->stats.V[readFeatSum->stats.yesWLmatch] += readFeatSum->stats.V[readFeatSum->stats.yesWLmatch_MultiFeature]; - for (uint32 iCB=0; iCBnReadPerCBmax) - nReadPerCBmax=nr; - readFeatSum->stats.V[readFeatSum->stats.nMatch] += nr; - }; - - for (int ii=0; iiaddStats(*readFeatAll[ii]); - readBarSum->addStats(*readBarAll[ii]); - }; - - time(&rawTime); - P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Finished reading reads from Solo files nCB="<statsOut(*statsStream); - *statsStream << setw(50)<< pSolo.featureNames[featureType] <<":\n"; + //output + ofstream *statsStream = &ofstrOpen(outputPrefix+"Features.stats",ERROR_OUT, P); readFeatSum->statsOut(*statsStream); + statsStream->close(); + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Solo: writing raw matrix" <logMain << timeMonthDayTime(rawTime) << " ... Solo: cell filtering" < +#include +#include "serviceFuns.cpp" +#include /* log */ + +void SoloFeature::quantTranscript() +{//velocyto counting gets info from Gene counting + time_t rawTime; + + if (pSolo.clusterCBfile=="-") + return;//no transcript quantification w/o cluster file + + std::unordered_map clusterCBind; //for each CB - cluster index of detected CB + std::set clusterInd; //cluster index for each cluster - the integer from clusterCBfile + {//load cluster information + ifstream &clusterStream = ifstrOpen(pSolo.clusterCBfile, ERROR_OUT, "SOLUTION: check the path and permissions of the cluster CB file: " + pSolo.clusterCBfile, P); + string seq1; + while (clusterStream >> seq1) { + uint32 icl1; + clusterStream >> icl1; + uint64 cb1; + if (convertNuclStrToInt64(seq1,cb1)) {//convert to 2-bit format + auto cb1it=std::equal_range(pSolo.cbWL.begin(), pSolo.cbWL.end(), cb1); //find iterator in WL matching cb1 + uint32 cb1ind=(uint32) (cb1it.first-pSolo.cbWL.begin()); //substract WL.begin iterator to find index in WL + if (cb1ind < pSolo.cbWL.size()) {//otherwise cb1 is not in WL + clusterCBind[cb1ind]=icl1; //map: key=CB, value=cluster index + clusterInd.emplace(icl1); //ordered set of cluster indexes + } else { + P.inOut->logMain << "WARNING: cluster CB sequence not present in whitelist and is ignored: " << seq1 <logMain << "WARNING: cluster CB sequence contains non-ACGT base and is ignored: " << seq1 <transcriptDistCount; //transcriptDistCount is accumulated while mapping, from reads that map uniquely + vector trDistFun(trDistCount.size(),0.0); + vector trDistFunTrFactor(Trans.nTr,0.0); + + {//process distance distribution function + //running average + int32 runAverN=50, runAverStart=0; + //for (uint32 ii=0; iitrDistFun[imax]) + imax++; //find maximum going forward from imax=1000 + P.inOut->logMain << "SoloQuant: distance distribution past maximum = " << imax <logMain << "SoloQuant: distance distribution cutoff = " << imax <close(); + + //normalization factors for all transcripts + vector trDistFunCum(trDistFun); + std::partial_sum(trDistFun.begin(), trDistFun.end(), trDistFunCum.begin()); + for (uint32 ii=0; ii for each read with the same umi + map>> mapTrDist; + + //////////// input records + for (int iThread=0; iThreadstreamReads; + streamReads->flush(); + streamReads->seekg(0,ios::beg); + + string line1; + while (std::getline(*streamReads, line1)) {//until the end of file + stringstream lineStream(line1); + uint32 cb, cbCl, nTr; + uint64 umi; + lineStream >> cb >> umi >> nTr; + + if (clusterCBind.count(cb)==0) //this cb is not in the clusters + continue; + + umi += (((uint64)cb)<<32); //to make UMI from different CB distinguishable + + cbCl=clusterCBind[cb]; + + vector tD; + tD.reserve(nTr); + for (uint32 ii=0; ii> tr1 >> d1; + if (d1>=trDistFun.size()) + continue; //do not record such outlier + + tD.push_back( {tr1, trDistFun[d1] + trDistFunTrFactor[tr1]} ); + }; + + if (tD.size()==0) + continue; + + std::sort(tD.begin(), tD.end(), [](const transcriptDistProbStruct &t1, const transcriptDistProbStruct &t2) { + return (t1.tr tD1; + tD1.reserve(mapTrDist[cbCl][umi].size()); + + for (uint32 iold=0; ioldtD[inew].tr) //move through the sorted lists + ++inew; //inew advances if old_trID>new_trID + + if (inew == tD.size() ) //end of tD reached + break; + + if (mapTrDist[cbCl][umi][iold].tr == tD[inew].tr) {//found match old_trID==new_trID + tD1.push_back({ tD[inew].tr, mapTrDist[cbCl][umi][iold].d + tD[inew].d });//add new log probability to the existing one + }; + }; + mapTrDist[cbCl][umi]=tD1;//replace with intersection + }; + }; + + time(&rawTime); + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Transcript3p counting: finished input" <> clusterExpression; //per cluster, relative abundance + //TODO parallelize this loop + for (auto & mapTrDist1 : mapTrDist) {//loop over cell clusters + auto &clTrDist=mapTrDist1.second; + + vector trUnique(Trans.nTr,0), trInitial(Trans.nTr,0);//counts of unique read for each transcripts (i.e. reads that map uniquely only to this transcript) + uint64 nUMItot=0, nUMI0=0, nUMI1=0; + + {//pre-process mapTrDist: + auto clTrDist1=clTrDist.begin(); + while ( clTrDist1!=clTrDist.end() ) {//loop over UMIs + auto &trDist=clTrDist1->second; + + if (trDist.size()==0) { + clTrDist1=clTrDist.erase(clTrDist1); + nUMI0++;//these are cases where the intersection of transcript from different reads with the same UMI is *empty* + continue; + } else if (trDist.size()==1) { + trUnique[trDist[0].tr]++; + trInitial[trDist[0].tr] += 1.0; + clTrDist1=clTrDist.erase(clTrDist1); + nUMI1++;//only one transcript in the intersection, i.e. unique mappers + nUMItot++; + continue; + }; + + double max1= std::max_element(trDist.begin(), trDist.end(), [](const transcriptDistProbStruct &t1, const transcriptDistProbStruct &t2) { + return (t1.d d; //finds maximum d + for (auto & tt : trDist) {//loop over transcripts in the UMI + trInitial[tt.tr] += 1.0/trDist.size();//for initialization, split each count between multimappers evenly and add it to unique mappers + tt.d =std::exp(tt.d-max1);//from sum(log(prob)) to product(prob), dividing by the max element to avoid underflow + }; //this constant factor does not matter, since only the ratios of tt.d matter + + nUMItot++; + clTrDist1++; + }; + P.inOut->logMain << timeMonthDayTime(rawTime) << " ... Transcript3p counting: cluster " << mapTrDist1.first <<" nUMItot="<logMain << timeMonthDayTime(rawTime) << " ... Transcript3p counting: finished cluster" << mapTrDist1.first <0) + nCellGeneEntries++; + + countMatrixStream << Trans.nTr <<' '<< *std::max_element(clusterInd.begin(),clusterInd.end()) <<' '<< nCellGeneEntries << '\n'; + + for (auto & ctpm : clusterExpression) + for (auto itt=ctpm.second.begin(); itt!=ctpm.second.end(); itt++) + if (*itt>0) + countMatrixStream << itt-ctpm.second.begin()+1 <<' '<< ctpm.first <<' '<< *itt << '\n'; + + countMatrixStream.flush(); + }; + + ofstream &outStr=ofstrOpen(outputPrefix+"/features.tsv",ERROR_OUT, P); + for (uint32 ii=0; iilogMain << timeMonthDayTime(rawTime) << " ... Transcript3p counting: finished transcript quantification" <cbReadCount[] + */ + + //find boundaries for cells + uint64 nReadRec=std::accumulate(readFeatSum->cbReadCount.begin(), readFeatSum->cbReadCount.end(), 0LLU); + //for ( auto &cbrc : readFeatSum->cbReadCount ) + // nReadRec += cbrc; + + uint64 nReadRecBin=nReadRec/pSolo.redistrReadsNfiles; + + P.inOut->logMain << " Redistributing reads into "<< pSolo.redistrReadsNfiles <<"files; nReadRec="<< nReadRec <<"; nReadRecBin="<< nReadRecBin <cbReadCount[indCB[icb]]; + if (nreads>=nReadRecBin) { + ind++; + redistrFilesCBfirst.push_back(icb+1); + redistrFilesNreads.push_back(nreads); + nreads=0; + }; + }; + if (nreads>0) { + redistrFilesCBfirst.push_back(nCB); + redistrFilesNreads.push_back(nreads); + }; + + //open output files + redistrFilesStreams.resize(redistrFilesNreads.size()); + for (uint32 ii=0; iistreamReads->clear();//this is needed if eof was reached before + readFeatAll[ii]->streamReads->seekg(0,ios::beg); + + while ( true ) { + string line1; + getline(*readFeatAll[ii]->streamReads,line1); + if (line1.empty()) { + break; + }; + + istringstream line1stream(line1); + uint64 cb1, umi; + line1stream >> umi >> cb1 >> cb1; + if (featureType==SoloFeatureTypes::SJ) + line1stream >> cb1; + line1stream >> cb1; + + *redistrFilesStreams[redistrFilesCBindex[indCBwl[cb1]]] << line1 <<'\n'; + + }; + //TODO: delete streamReads files one by one to save disk space + }; + + //close files + //for (uint32 ii=0; iiflush(); +}; + diff --git a/source/SoloFeature_statsOutput.cpp b/source/SoloFeature_statsOutput.cpp new file mode 100644 index 00000000..fb5ab68d --- /dev/null +++ b/source/SoloFeature_statsOutput.cpp @@ -0,0 +1,80 @@ +#include "SoloFeature.h" +#include "streamFuns.h" +#include "Stats.h" +#include "GlobalVariables.h" + +void SoloFeature::statsOutput() +{ + ofstream &strOut=ofstrOpen(outputPrefix+"Summary.csv", ERROR_OUT, P); + //Sequencing + strOut << "Number of Reads," << g_statsAll.readN <<'\n'; + strOut << "Reads With Valid Barcodes," << 1.0 - double( readBarSum->stats.numInvalidBarcodes() + readFeatSum->stats.numInvalidBarcodes() )/g_statsAll.readN <<'\n'; + strOut << "Sequencing Saturation," << readFeatSum->stats.numSequencingSaturation() <<'\n'; + + if (pSolo.type != pSolo.SoloTypes::SmartSeq) {//qualHist for CB+UMI + uint64 q30=0, ntot=0; + for (uint32 ix=0; ix<256; ix++) { + ntot += readBarSum->qualHist[ix]; + if (ix >= (P.readQualityScoreBase + 30)) + q30 += readBarSum->qualHist[ix]; + }; + + strOut << "Q30 Bases in CB+UMI," << double(q30)/ntot <<'\n'; + }; + + {//qualHist for RNA + uint64 q30=0, ntot=0; + for (int ichunk=0; ichunkRA->qualHist[imate][ix]; + if (ix >= (P.readQualityScoreBase + 30)) + q30 += RAchunk[ichunk]->RA->qualHist[imate][ix]; + }; + }; + }; + strOut << "Q30 Bases in RNA read," << double(q30)/ntot <<'\n'; + }; + + strOut << "Reads Mapped to Genome: Unique+Multiple," << double(g_statsAll.mappedReadsU+g_statsAll.mappedReadsM)/g_statsAll.readN <<'\n'; + strOut << "Reads Mapped to Genome: Unique," << double(g_statsAll.mappedReadsU)/g_statsAll.readN <<'\n'; + + string mapfeat=SoloFeatureTypes::Names[featureType]; + + strOut << "Reads Mapped to "<< mapfeat << ": Unique+Multipe " << SoloFeatureTypes::Names[featureType] <<"," << double( readFeatSum->stats.numMappedToTranscriptome() )/g_statsAll.readN <<'\n'; + strOut << "Reads Mapped to "<< mapfeat << ": Unique " << SoloFeatureTypes::Names[featureType] <<"," << double( readFeatSum->stats.numMappedToTranscriptomeUnique() )/g_statsAll.readN <<'\n'; + + if (pSolo.cellFilter.type[0]!="None" + && (featureType==SoloFeatureTypes::Gene || featureType==SoloFeatureTypes::GeneFull + || featureType==SoloFeatureTypes::GeneFull_ExonOverIntron || featureType==SoloFeatureTypes::GeneFull_Ex50pAS)) { + //if (pSolo.cellFilter.type[0]=="CellRanger2.2") + { + strOut << "Estimated Number of Cells," << filteredCells.nCells <<'\n'; + + strOut << "Unique Reads in Cells Mapped to " << SoloFeatureTypes::Names[featureType] << "," << filteredCells.nReadInCellsUnique <<'\n'; + strOut << "Fraction of Unique Reads in Cells," << double(filteredCells.nReadInCellsUnique) / readFeatSum->stats.numMappedToTranscriptomeUnique() <<'\n'; + strOut << "Mean Reads per Cell," << filteredCells.meanReadPerCellUnique <<'\n'; + strOut << "Median Reads per Cell," << filteredCells.medianReadPerCellUnique <<'\n'; + + strOut << "UMIs in Cells," << filteredCells.nUMIinCells <<'\n'; + strOut << "Mean UMI per Cell," << filteredCells.meanUMIperCell <<'\n'; + strOut << "Median UMI per Cell," << filteredCells.medianUMIperCell <<'\n'; + + strOut << "Mean " << SoloFeatureTypes::Names[featureType] << " per Cell," << filteredCells.meanGenePerCell <<'\n'; + strOut << "Median " << SoloFeatureTypes::Names[featureType] << " per Cell," << filteredCells.medianGenePerCell <<'\n'; + strOut << "Total " << SoloFeatureTypes::Names[featureType] << " Detected," << filteredCells.nGeneDetected <<'\n'; + }; + + //output UMI per cell, sorted + ofstream &strOutUMIperCell = ofstrOpen(outputPrefix+"UMIperCellSorted.txt", ERROR_OUT, P); + + for (auto & n : nUMIperCBsorted) { + if (n==0) + break; + strOutUMIperCell << n <<'\n'; + }; + strOutUMIperCell.close(); + }; + + strOut.close(); +}; \ No newline at end of file diff --git a/source/SoloFeature_sumThreads.cpp b/source/SoloFeature_sumThreads.cpp new file mode 100644 index 00000000..3e47fc17 --- /dev/null +++ b/source/SoloFeature_sumThreads.cpp @@ -0,0 +1,91 @@ +#include "SoloFeature.h" +#include "streamFuns.h" +#include "TimeFunctions.h" +#include "SequenceFuns.h" +#include "Stats.h" +#include "GlobalVariables.h" + +void SoloFeature::sumThreads() +{ + //stats + nReadsInput=g_statsAll.readN+1; //reserve 1 extra + + ///////////////////////////// collect RAchunk->RA->soloRead->readFeat + for (int ii=0; iiRA->soloRead->readFeat[pSolo.featureInd[featureType]]; + readFeatAll[ii]->streamReads->flush(); + readFeatSum->addCounts(*readFeatAll[ii]); + }; + + // if WL was not defined + if (!pSolo.cbWLyes) {//now we can define WL and counts ??? we do not need to do it for every feature??? + pSolo.cbWLsize=readFeatSum->cbReadCountMap.size(); + pSolo.cbWL.resize(pSolo.cbWLsize); + pSolo.cbWLstr.resize(pSolo.cbWLsize); + uint64 ii=0; + for (auto &cb : readFeatSum->cbReadCountMap) { + pSolo.cbWL[ii] = cb.first; + pSolo.cbWLstr[ii] = convertNuclInt64toString(pSolo.cbWL[ii],pSolo.cbL); + ii++; + }; + readFeatSum->cbReadCount.resize(pSolo.cbWLsize); + readBarSum->cbReadCountExact.resize(pSolo.cbWLsize); + + uint64 icb=0; + for (auto ii=readFeatSum->cbReadCountMap.cbegin(); ii!=readFeatSum->cbReadCountMap.cend(); ++ii) { + pSolo.cbWL[icb]=ii->first; + readFeatSum->cbReadCount[icb]=ii->second; + readBarSum->cbReadCountExact[icb]=ii->second; + ++icb; + }; + + //pseudocounts + if (pSolo.CBmatchWL.mm1_multi_pc) { + for (uint32 ii=0; iicbReadCountExact[ii]++;//add one to exact counts + }; + }; + }; + + // if restarting from _STARtmp/solo* file + if (P.runRestart.type==1) {//this could happen if the run is restarted. Would be better to save/load cbReadCount, or recalculate it from + for (int ii=0; iistreamReads->clear(); //just in case EOF was reached in previous reading + readFeatAll[ii]->streamReads->seekg(0,ios::beg); + string line1; + while (std::getline(*readFeatAll[ii]->streamReads, line1)) { + istringstream line1stream(line1); + uint64 cb1; + line1stream >> cb1 >> cb1 >> cb1; + if (featureType==SoloFeatureTypes::SJ) + line1stream >> cb1; + line1stream >> cb1; + //if (cb1>readFeatSum->cbReadCount.size()) + // continue;//this should not happen! + readFeatSum->cbReadCount[cb1]++; + }; + }; + }; + + //detected CBs + nCB=0;nReadsMapped=0; + for (uint32 ii=0; iicbReadCount[ii]>0) { + nCB++; + nReadsMapped += readFeatSum->cbReadCount[ii]; + }; + }; + + indCBwl.resize(pSolo.cbWLsize, (uint32) -1); + indCB.resize(nCB); + nCB=0;//will count it again below + for (uint32 ii=0; iicbReadCount[ii]>0) { + indCB[nCB]=ii; + indCBwl[ii]=nCB; + ++nCB; + }; + }; + +}; + diff --git a/source/SoloFilteredCells.h b/source/SoloFilteredCells.h new file mode 100644 index 00000000..435d233d --- /dev/null +++ b/source/SoloFilteredCells.h @@ -0,0 +1,33 @@ +#ifndef H_SoloFilteredCells +#define H_SoloFilteredCells + +class SoloFilteredCells { +public: + array C; + + uint64 &nCells =C[0]; + uint64 &nReadInCells =C[1]; + uint64 &medianReadPerCellUnique =C[2]; + uint64 &meanReadPerCellUnique =C[3]; + uint64 &nUMIinCells =C[4]; + uint64 &medianUMIperCell =C[5]; + uint64 &meanUMIperCell =C[6]; + uint64 &nGeneInCells =C[7]; + uint64 &medianGenePerCell =C[8]; + uint64 &meanGenePerCell =C[9]; + uint64 &nGeneDetected =C[10]; + uint64 &nCellsSimple =C[11]; + uint64 &nReadInCellsUnique =C[12]; + + vector nReadPerCellUnique, nGenePerCell; + vector filtVecBool; + + void reset(uint64 nCells) { + C={0}; + nReadPerCellUnique.clear(); nReadPerCellUnique.reserve(16384); + nGenePerCell.clear(); nGenePerCell.reserve(16384); + filtVecBool.clear(); filtVecBool.resize(nCells, false); + }; +}; + +#endif diff --git a/source/SoloRead.cpp b/source/SoloRead.cpp index a49f7c59..54b4da41 100755 --- a/source/SoloRead.cpp +++ b/source/SoloRead.cpp @@ -5,7 +5,9 @@ SoloRead::SoloRead(Parameters &Pin, int32 iChunkIn) : iChunk(iChunkIn), P(Pin), readBar = new SoloReadBarcode(P); if (pSolo.type==0) - return; + return; + if (pSolo.type==pSolo.SoloTypes::CB_samTagOut) + return; readFeat = new SoloReadFeature*[pSolo.nFeatures]; diff --git a/source/SoloRead.h b/source/SoloRead.h index 21e7b1d2..29e6e153 100755 --- a/source/SoloRead.h +++ b/source/SoloRead.h @@ -3,6 +3,7 @@ #include "SoloReadBarcode.h" #include "SoloReadFeature.h" +#include "ReadAnnotations.h" class SoloRead { public: @@ -10,7 +11,7 @@ class SoloRead { SoloReadFeature **readFeat; SoloRead(Parameters &Pin, int32 iChunkIn); - void record(uint64 nTr, set &readTrGenes, set &readGenes, Transcript *alignOut); + void record(uint64 nTr, Transcript **alignOut, uint64 iRead, ReadAnnotations &readAnnot); private: const int32 iChunk; diff --git a/source/SoloReadBarcode.cpp b/source/SoloReadBarcode.cpp index 9c39ad46..79d79df3 100755 --- a/source/SoloReadBarcode.cpp +++ b/source/SoloReadBarcode.cpp @@ -1,7 +1,7 @@ #include "SoloReadBarcode.h" #include "streamFuns.h" -SoloReadBarcode::SoloReadBarcode(Parameters &Pin) : P(Pin), pSolo(P.pSolo) +SoloReadBarcode::SoloReadBarcode(Parameters &P) : P(P), pSolo(P.pSolo) { if (pSolo.type==0) return; @@ -10,10 +10,7 @@ SoloReadBarcode::SoloReadBarcode(Parameters &Pin) : P(Pin), pSolo(P.pSolo) stats.V[ii]=0; if (pSolo.cbWLyes) { - cbReadCountExact = new uint32[pSolo.cbWL.size()]; - for (uint32 ii=0; ii #include "IncludeDefine.h" #include "Parameters.h" +#include "SoloReadBarcodeStats.h" class SoloReadBarcode { +private: + Parameters &P; + public: + ParametersSolo &pSolo; + + uint32 homoPolymer[4];//homopolymer constants - string cbSeq, umiSeq, cbQual, umiQual; - uint64 cbB; - uint32 umiB; - int64 cbI; - int32 cbMatch;//0=exact, 1=1 match with 1MM, 2= >1 matches with 1MM + string cbSeq, umiSeq, cbQual, umiQual, bSeq, bQual; + string cbSeqCorrected; + uint64 umiB; + //int64 cbI; + int32 cbMatch;//-1: no match, 0: exact, 1: 1 match with 1MM, >1: # of matches with 1MM + int32 umiCheck;//umi check status string cbMatchString;//CB matches and qualities - vector cbMatchInd;//matches - uint32 *cbReadCountExact; + vector cbMatchInd;//matches + vector cbReadCountExact; + //map cbReadCountMap;//count read per CB for no WL - struct { - enum { nNinBarcode, nUMIhomopolymer, nTooMany, nNoMatch, nStats}; - uint64 V[nStats]; - vector names={"nNinBarcode","nUMIhomopolymer","nTooMany","nNoMatch"}; - } stats; + array qualHist; + SoloReadBarcodeStats stats; SoloReadBarcode(Parameters &Pin); - void getCBandUMI(string &readNameExtra); + void getCBandUMI(char **readSeq, char **readQual, uint64 *readLen, const string &readNameExtraIn, const uint32 &readFilesIndex, const char *readName); void addCounts(const SoloReadBarcode &rfIn); void addStats(const SoloReadBarcode &rfIn); void statsOut(ofstream &streamOut); + void matchCBtoWL(string &cbSeq1, string &cbQual1, vector &cbWL, int32 &cbMatch1, vector &cbMatchInd1, string &cbMatchString1); + bool convertCheckUMI(); + void addStats(const int32 cbMatch1); + -private: - Parameters &P; - ParametersSolo &pSolo; +protected: + void readNameExtra(); }; #endif diff --git a/source/SoloReadBarcodeStats.h b/source/SoloReadBarcodeStats.h new file mode 100644 index 00000000..165ca8ef --- /dev/null +++ b/source/SoloReadBarcodeStats.h @@ -0,0 +1,27 @@ +#ifndef H_SoloReadBarcodeStats +#define H_SoloReadBarcodeStats +#include "IncludeDefine.h" + +class SoloReadBarcodeStats { +public: + vector names; + enum { noNoAdapter, noNoUMI, noNoCB, noNinCB, noNinUMI, noUMIhomopolymer, noNoWLmatch, noTooManyMM, noTooManyWLmatches, yesWLmatchExact, yesOneWLmatchWithMM, yesMultWLmatchWithMM, nStats}; + uint64 V[nStats]; + SoloReadBarcodeStats() + { + names={"noNoAdapter", "noNoUMI", "noNoCB", "noNinCB", "noNinUMI", "noUMIhomopolymer","noNoWLmatch", "noTooManyMM", "noTooManyWLmatches", "yesWLmatchExact", "yesOneWLmatchWithMM", "yesMultWLmatchWithMM"}; + for (uint32 ii=0; ii &cbWL, int32 &cbMatch1, vector &cbMatchInd1, string &cbMatchString1) { - if (pSolo.type==0) - return; - cbI=-999; - - cbMatch=-1; - cbMatchString=""; - - cbSeq=readNameExtra.substr(pSolo.cbS-1,pSolo.cbL); - umiSeq=readNameExtra.substr(pSolo.umiS-1,pSolo.umiL); - - uint32 qualStart = readNameExtra.find(' ',pSolo.cbL+pSolo.umiL); - cbQual=readNameExtra.substr(qualStart+pSolo.cbS,pSolo.cbL); - umiQual=readNameExtra.substr(qualStart+pSolo.umiS,pSolo.umiL); - - //check UMIs, return if bad UMIs - if (convertNuclStrToInt32(umiSeq,umiB)!=-1) {//convert and check for Ns - stats.V[stats.nNinBarcode]++;//UMIs are not allowed to have Ns - return; - }; - if (umiB==homoPolymer[0] || umiB==homoPolymer[1] || umiB==homoPolymer[2] || umiB==homoPolymer[3]) { - stats.V[stats.nUMIhomopolymer]++; - return; - }; - + cbMatch1=-1; + cbMatchString1=""; + cbMatchInd1.clear(); //convert CB and check for Ns - int64 posN=convertNuclStrToInt64(cbSeq,cbB); + uint64 cbB1; + int64 posN=convertNuclStrToInt64(cbSeq1,cbB1); if (!pSolo.cbWLyes) {//no whitelist - no search if (posN!=-1) {//Ns are present, discard this read - stats.V[stats.nNinBarcode]++; + cbMatch1=-2; + //stats.V[stats.nNinBarcode]++; } else {//no Ns - cbI=(int64) cbB;//all possible barcodes are accepted. This will overflow if CB is longer than 31b - cbMatch=0; + //cbI=(int64) cbB1; + cbMatchInd1.push_back(cbB1);//all possible barcodes are accepted. This will overflow if CB is longer than 31b + cbMatchString1 = to_string(cbB1); + cbMatch1=0; }; return; }; if (posN==-2) {//>2 Ns, might already be filtered by Illumina - stats.V[stats.nNinBarcode]++; + cbMatch1=-2; + //stats.V[stats.nNinBarcode]++; return; } else if (posN==-1) {//no Ns, count only for featureType==gene - cbI=binarySearchExact(cbB,pSolo.cbWL.data(),pSolo.cbWL.size()); + int64 cbI=binarySearchExact(cbB1,cbWL.data(),cbWL.size()); if (cbI>=0) {//exact match - cbReadCountExact[cbI]++;//note that this simply counts reads per exact CB, no checks of genes or UMIs - cbMatch=0; + cbMatchInd1.push_back((uint64) cbI); + cbMatchString1 = to_string(cbMatchInd1[0]); + cbMatch1=0; return; }; }; + + if (!pSolo.CBmatchWL.mm1) //only exact matches allowed + return; + cbMatch1=0; if (posN>=0) {//one N - uint32 posNshift=2*(pSolo.cbL-1-posN);//shift bits for posN + uint32 posNshift=2*(cbSeq1.size()-1-posN);//shift bits for posN + bool matched = false; for (uint32 jj=0; jj<4; jj++) { - uint64 cbB1=cbB^(jj<(cbB1,pSolo.cbWL.data(),pSolo.cbWL.size()); - if (cbI1>=0) { - if (cbI>=0) {//had another match already - stats.V[stats.nTooMany]++; - return;//with N in CB, do not allow matching >1 in WL + uint64 cbB11=cbB1^(jj<(cbB11,cbWL.data(),cbWL.size()); + if (cbI1>=0) {//found match + if (!pSolo.CBmatchWL.mm1_multi_Nbase && matched) { + cbMatchInd1.clear(); + cbMatch1=-3; + break; //this is 2nd match, not allowed for N-bases }; - cbI=cbI1; + matched = true; + //output all + cbMatchInd1.push_back(cbI1); + ++cbMatch1; + cbMatchString1 += ' ' +to_string(cbI1) + ' ' + cbQual1[posN]; }; }; - if (cbI>=0) { - cbMatch=1; - return; - } else {//no match - stats.V[stats.nNoMatch]++; - return; + } else {//look for 1MM; posN==-1, no Ns + for (uint32 ii=0; ii(cbB1^(jj<<(ii*2)),cbWL.data(),cbWL.size()); + if (cbI1>=0) {//found match + //output all + cbMatchInd1.push_back(cbI1); + ++cbMatch1; + cbMatchString1 += ' ' +to_string(cbI1) + ' ' + cbQual1.at(cbSeq1.size()-1-ii); + }; + }; }; }; + if (cbMatch1==0) {//no matches + //stats.V[stats.noNoWLmatch]++; + cbMatch1=-1; + } else if (cbMatch1==1) {//1 match, no need to record the quality + cbMatchString1 = to_string(cbMatchInd1[0]); + } else if (!pSolo.CBmatchWL.mm1_multi) {//>1 matches, but this is not allowed + cbMatch1=-3; + cbMatchInd1.clear(); + cbMatchString1=""; + };// else cbMatch contains number of matches, and cbMatchString has CBs and qualities +}; + +void SoloReadBarcode::addStats(const int32 cbMatch1) +{ + if (!pSolo.cbWLyes) //no stats if no WL + return; + + switch (cbMatch1) { + case 0://exact matches + cbReadCountExact[cbMatchInd[0]]++;//note that this simply counts reads per exact CB, no checks of genes or UMIs + stats.V[stats.yesWLmatchExact]++; + break; + case 1: //one WL match counted here, but they may still get rejected in SoloReadFeature_inputRecords.cpp + stats.V[stats.yesOneWLmatchWithMM]++; + break; + default: //multiple WL matches are counted here, but they may still get rejected in SoloReadFeature_inputRecords.cpp + stats.V[stats.yesMultWLmatchWithMM]++; + break; + case -1 : + stats.V[stats.noNoWLmatch]++; + break; + case -2 : + stats.V[stats.noNinCB]++; + break; + case -3 : + stats.V[stats.noTooManyWLmatches]++; + break; + case -11 : + stats.V[stats.noNoCB]++;//CB sequence cannot be extracted + break; + case -12 : + stats.V[stats.noTooManyMM]++; + break; + }; +}; - //look for 1MM, posN==-1, no Ns - cbMatch=0; +/////////////////////////////////////////////////////////////////////////////////////// +bool SoloReadBarcode::convertCheckUMI() +{//check UMIs, return if bad UMIs + if (convertNuclStrToInt64(umiSeq,umiB)!=-1) {//convert and check for Ns + stats.V[stats.noNinUMI]++;//UMIs are not allowed to have Ns + umiCheck=-23; + return false; + }; + if (umiB==homoPolymer[0] || umiB==homoPolymer[1] || umiB==homoPolymer[2] || umiB==homoPolymer[3]) { + stats.V[stats.noUMIhomopolymer]++; + umiCheck=-24; + return false; + }; + return true; +}; + +////////////////////////////////////////////////////////////////////////////////////// +void SoloReadBarcode::getCBandUMI(char **readSeq, char **readQual, uint64 *readLen, const string &readNameExtraIn, const uint32 &readFilesIndex, const char *readName) +{ + if (pSolo.type==0) + return; + +///////////////////////////SmartSeq + if (pSolo.type==pSolo.SoloTypes::SmartSeq) { + cbSeq=cbQual=cbSeqCorrected=""; //TODO make cbSeq=file label + cbMatch=0; + cbMatchInd={readFilesIndex}; + cbMatchString=to_string(cbMatchInd[0]); + addStats(cbMatch); + return; + }; + + cbMatch=-1; + cbMatchString=""; cbMatchInd.clear(); - for (uint32 ii=0; ii(cbB^(jj<<(ii*2)),pSolo.cbWL.data(),pSolo.cbWL.size()); - if (cbI1>=0) {//found match - //output all - cbI=cbI1; - cbMatchInd.push_back(cbI1); - ++cbMatch; - cbMatchString += ' ' +to_string(cbI1) + ' ' + cbQual.at(pSolo.cbL-1-ii); + + /////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////// bSeq and bQual + if (P.readFilesTypeN != 10) {//not SAM: barcode seq/qual are at the beginning of readNameExtra + bSeq=std::string(readSeq[pSolo.barcodeRead], readLen[pSolo.barcodeRead]); + bQual=std::string(readQual[pSolo.barcodeRead], readLen[pSolo.barcodeRead]); + + } else {//SAM: barcode seq/qual is collected from SAM tags + uint32 pos1 = readNameExtraIn.find_first_not_of(" \t"); //to remove whitespace + string readNameExtraT; + if (pos1==0) { + readNameExtraT = '\t' + readNameExtraIn;//\t needs to be in front of readNameExtra for efficient search + } else { + readNameExtraT = readNameExtraIn; + readNameExtraT[pos1] = '\t'; + }; + + bSeq = {}; + for (auto &tag: pSolo.samAtrrBarcodeSeq) { + size_t pos1 = readNameExtraT.find(tag); //find tag + if ( pos1 == std::string::npos ) { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR in input read file: could not find barcode sequence SAM attribute " << tag << " in read " <logMain, EXIT_CODE_INPUT_FILES, P); + }; + pos1 +=6; //skip 6 chars, e.g. \tCB:Z: + size_t pos2 = readNameExtraT.find('\t', pos1); //find next \t + bSeq += readNameExtraT.substr(pos1,pos2-pos1); + }; + + bQual = {}; + if (pSolo.samAtrrBarcodeQual.size()==0) {//if quality tags are not supplied + bQual.resize(bSeq.size(), 'H'); + } else { + for (auto &tag: pSolo.samAtrrBarcodeQual) { + size_t pos1 = readNameExtraT.find(tag); //find tag, and skip 6 chars, e.g. \tCB:Z: + if ( pos1 == std::string::npos ) { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR in input read file: could not find barcode qualities SAM attribute " << tag << " in read " <logMain, EXIT_CODE_INPUT_FILES, P); + }; + pos1 += 6; //skip 6 chars, e.g. \tCB:Z: + size_t pos2 = readNameExtraT.find('\t', pos1); //find next \t + bQual += readNameExtraT.substr(pos1,pos2-pos1); + }; + }; + + if (bQual.size() != bSeq.size()) { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR in input read file: the total length of barcode qualities is " << bQual.size() << " not equal to the sequence length " << bSeq.size() <<"\n" ; + errOut << "Read ID="<< readName <<" ; Qualities="<< bQual <<" ; Sequence="<< bSeq << " ; Read SAM attributes: "<< readNameExtraT <<"\n"; + errOut << "SOLUTION: make sure correct attributes are listed in --soloInputSAMattrBarcodeQual\n"; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + }; + }; + + if ( bSeq.size() != P.pSolo.bL ) {//check barcodeRead length. bSeq.size == bQual.size here, this should have been checked before + if (P.pSolo.bL > 0) { + ostringstream errOut; + errOut << "EXITING because of FATAL ERROR in input read file: the total length of barcode sequence is " << bSeq.size() << " not equal to expected " << P.pSolo.bL <<"\n" << + "Read ID=" << readName <<" ; Sequence=" << bSeq <<'\n' << + "SOLUTION: check the formatting of input read files.\n" << + "If UMI+CB length is not equal to the barcode read length, specify barcode read length with --soloBarcodeReadLength\n" << + "To avoid checking of barcode read length, specify --soloBarcodeReadLength 0" ; + exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); + } else if (bSeq.size()0 + bSeq.append(P.pSolo.cbumiL-bSeq.size(), 'N'); + bQual.append(P.pSolo.cbumiL-bQual.size(), 'H'); + }; + }; + + if ( pSolo.type != pSolo.SoloTypes::CB_UMI_Simple ) { + for (uint64 ix=0; ix<( P.pSolo.bL>0 ? P.pSolo.bL : bQual.size() ); ix++) {//bL==0 use the whole barcode read for quality scores histogram + qualHist[(uint8)bQual[ix]]++; + }; + }; + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////// cbSeq and umiSeq, and match CB to WL, different CB_UMI types + ///////////////////////////CB_UMI_Simple a.k.a Droplet + if ( pSolo.type==pSolo.SoloTypes::CB_UMI_Simple ) { + cbSeq=bSeq.substr(pSolo.cbS-1,pSolo.cbL); + umiSeq=bSeq.substr(pSolo.umiS-1,pSolo.umiL); + cbQual=bQual.substr(pSolo.cbS-1,pSolo.cbL); + umiQual=bQual.substr(pSolo.umiS-1,pSolo.umiL); + + for (uint64 ix=0; ix pSolo.adapterMismatchesNmax) { + stats.V[stats.noNoAdapter]++; + cbMatch=-21; + return; //no adapter found }; }; + + if (!pSolo.umiV.extractBarcode(bSeq, bQual, adapterStart, umiSeq, umiQual)) { + stats.V[stats.noNoUMI]++; + cbMatch=-22; + return; + }; + + bool cbMatchGood=true; + if (!convertCheckUMI()) { + cbMatchGood = false;//CB matching will not be done, just extract the sequences + cbMatch = umiCheck; + }; + + cbMatchInd={0}; + for (auto &cb : pSolo.cbV) {//cycle over multiple barcodes + + string cbSeq1, cbQual1; + if ( !cb.extractBarcode(bSeq, bQual, adapterStart, cbSeq1, cbQual1) + || cbSeq1.size() < cb.minLen || cbSeq1.size() >= cb.wl.size() || cb.wl[cbSeq1.size()].size()==0 ) { + //barcode cannot be extracted + if (cbMatchGood) { + cbMatch=-11; + cbMatchGood=false; + }; + }; + cbSeq += cbSeq1 + "_"; + cbQual += cbQual1 + "_"; + + if (!cbMatchGood) + continue; //continue - to be able to record full cbSeq, cbQual, but no need to match to the WL + + uint64 cbLen1 = cbSeq1.size(); + if ( pSolo.CBmatchWL.ParseBio_ED3 ) { + cbMatch=0; //0: no MM, 1: >=1MM. 2: multi-match: not allowed for this option + uintCB cbB1; + int64 posN=convertNuclStrToInt64(cbSeq1,cbB1); + if (posN!=-1) {//Ns in barcode: no good match + cbMatch = -2; + cbMatchGood = false; + } else { + int64 cbI=binarySearchExact(cbB1,cb.wl[cbSeq1.size()].data(),cb.wl[cbLen1].size()); + if (cbI<0) {//exact match + cbI=binarySearchExact(cbB1,cb.wlEd[cbLen1].data(),cb.wlEd[cbLen1].size()); + if (cbI>=0) {//find match in the edited list + cbMatch = 1; //>=1MM + cbI = cb.wlEdInd[cbLen1][cbI]; + cbMatchInd[0] += cb.wlFactor*(cbI+cb.wlAdd[cbLen1]); + } else { + cbMatch = -1; + cbMatchGood = false; + }; + }; + }; + } else {// Exact or 1MM + int32 cbMatch1; + vector cbMatchInd1; + matchCBtoWL(cbSeq1, cbQual1, cb.wl[cbLen1], cbMatch1, cbMatchInd1, cbMatchString); //cbMatchString is not used for now, multiple matches are not allowed + if (cbMatch1<0) {//no match + cbMatchGood=false; + cbMatch = cbMatch1; + } else if (cbMatch1>0 && cbMatch>0) {//this barcode has >1 1MM match, or previous barcode had a mismatch + cbMatchGood=false; + cbMatch = -12; //marks mismatches in multiple barcodes + } else {//good match + cbMatchInd[0] += cb.wlFactor*(cbMatchInd1[0]+cb.wlAdd[cbLen1]); + cbMatch=max(cbMatch,cbMatch1);//1 wins over 0 + }; + }; + }; + cbSeq.pop_back();//remove last "_" from file + cbQual.pop_back(); + + if (cbMatchGood) { + cbMatchString=to_string(cbMatchInd[0]); + }; }; - if (cbMatch==0) {//no matches - stats.V[stats.nNoMatch]++; - cbMatch=-1; - };// else cbMatch contains number of matches (1 or >1), and cbMatchString contains matches for >1 case + + addStats(cbMatch); }; diff --git a/source/SoloReadFeature.cpp b/source/SoloReadFeature.cpp index af13cabf..91f3abda 100755 --- a/source/SoloReadFeature.cpp +++ b/source/SoloReadFeature.cpp @@ -1,33 +1,35 @@ #include "SoloReadFeature.h" #include "streamFuns.h" +#include "SoloFeatureTypes.h" SoloReadFeature::SoloReadFeature(int32 feTy, Parameters &Pin, int iChunk) : featureType(feTy), P(Pin), pSolo(P.pSolo) { if (pSolo.type==0) return; - - for (uint32 ii=0; ii=0) { - strU_0 = &fstrOpen(P.outFileTmp+"/solo"+pSolo.featureNames[featureType]+"_0_"+std::to_string(iChunk),ERROR_OUT, P); - strU_1 = &fstrOpen(P.outFileTmp+"/solo"+pSolo.featureNames[featureType]+"_1_"+std::to_string(iChunk),ERROR_OUT, P); - strU_2 = &fstrOpen(P.outFileTmp+"/solo"+pSolo.featureNames[featureType]+"_2_"+std::to_string(iChunk),ERROR_OUT, P); + //open with flagDelete=false, i.e. try to keep file if it exists + streamReads = &fstrOpen(P.outFileTmp+"/solo"+SoloFeatureTypes::Names[featureType]+'_'+std::to_string(iChunk), ERROR_OUT, P, false); }; + + if (featureType==SoloFeatureTypes::Transcript3p) + transcriptDistCount.resize(10000,0); }; void SoloReadFeature::addCounts(const SoloReadFeature &rfIn) { if (pSolo.cbWLyes) {//WL - for (uint32 ii=0; iifirst] += ii->second; }; }; + + if (transcriptDistCount.size()>0) { + for (uint32 ii=0; ii cbReadCountMap; - - fstream *strU_0 ,*strU_1, *strU_2; //unique mappers, CB matches whitelist with 0,1>=2 MM + vector cbReadCount; + map cbReadCountMap; + + vector transcriptDistCount; + + bool readInfoYes ,readIndexYes; - struct { - enum { nUnmapped, nNoFeature, nAmbigFeature, nAmbigFeatureMultimap, nTooMany, nNoExactMatch, nExactMatch, nMatch, nCellBarcodes, nUMIs, nStats}; - uint64 V[nStats]; - vector names={"nUnmapped","nNoFeature","nAmbigFeature","nAmbigFeatureMultimap","nTooMany","nNoExactMatch","nExactMatch","nMatch","nCellBarcodes","nUMIs",}; - } stats; + fstream *streamReads; string cbSeq, umiSeq, cbQual, umiQual; + + SoloReadFeatureStats stats; SoloReadFeature (int32 feTy, Parameters &Pin, int iChunk); - void record(SoloReadBarcode &soloBar, uint nTr, set &readGene, set &readGeneFull, Transcript *alignOut); + void record(SoloReadBarcode &soloBar, uint nTr, Transcript **alignOut, uint64 iRead, ReadAnnotations &readAnnot); void addCounts(const SoloReadFeature &soloCBin); void addStats(const SoloReadFeature &soloCBin); void statsOut(ofstream &streamOut); - void inputRecords(uint32 **cbP, uint32 *cbReadCountExact); + void inputRecords(uint32 **cbP, uint32 cbPstride, vector &cbReadCountTotal, vector &readInfo); private: const int32 featureType; diff --git a/source/SoloReadFeatureStats.h b/source/SoloReadFeatureStats.h new file mode 100644 index 00000000..3a85c003 --- /dev/null +++ b/source/SoloReadFeatureStats.h @@ -0,0 +1,49 @@ +#ifndef H_SoloReadFeatureStats +#define H_SoloReadFeatureStats +#include "IncludeDefine.h" + +class SoloReadFeatureStats { +public: + vector names; + enum { noUnmapped, noNoFeature, noTooManyWLmatches, noMMtoWLwithoutExact, yesWLmatch, yessubWLmatchExact, yesWLmatch_UniqueFeature, yesWLmatch_MultiFeature, yessubWLmatch_MultiFeatureMultiGenomic, yesCellBarcodes, yesUMIs, nStats}; + uint64 V[nStats]; + SoloReadFeatureStats() + { + names={"noUnmapped","noNoFeature","noTooManyWLmatches","noMMtoWLwithoutExact","yesWLmatch","yessubWLmatchExact","yesWLmatch_UniqueFeature","yesWLmatch_MultiFeature","yessubWLmatch_MultiFeatureMultiGenomic","yesCellBarcodes","yesUMIs"}; + for (uint32 ii=0; ii #include "SoloReadFeature.h" -#include "binarySearch2.h" +#include "SoloCommon.h" +#include "SoloFeature.h" +#include "soloInputFeatureUMI.h" #include "serviceFuns.cpp" +void SoloReadFeature::inputRecords(uint32 **cbP, uint32 cbPstride, vector &cbReadCountTotal, vector &readInfo) +{ + streamReads->flush(); + streamReads->seekg(0,std::ios::beg); -bool inputFeatureUmi(fstream *strIn, int32 featureType, uint32 &feature, uint32 &umi, array,2> &sjAll) -{ - if (!(*strIn >> umi)) //end of file - return false; + //////////////////////////////////////////// standard features + uint32 feature; + uint64 umi, iread; + int32 cbmatch; + int64 cb; + vector trIdDist; + while (soloInputFeatureUMI(streamReads, featureType, readIndexYes, P.sjAll, iread, cbmatch, feature, umi, trIdDist)) { + if (feature == (uint32)(-1) && !readIndexYes) {//no feature => no record, this can happen for SJs + streamReads->ignore((uint32)-1, '\n'); + //stats.V[stats.noNoFeature]++; //need separate category for this + continue; + }; - if (featureType==0 || featureType==2) {//gene - *strIn >> feature; - } else if (featureType==1) {//sj - uint32 sj[2]; - *strIn >> sj[0] >> sj[1]; - feature=(uint32) binarySearch2(sj[0],sj[1],sjAll[0].data(),sjAll[1].data(),sjAll[0].size()); - }; + if (cbmatch<=1) {//single match + *streamReads >> cb; - return true; -}; + if ( pSolo.CBmatchWL.oneExact && cbmatch==1 && cbReadCountTotal[cb]==0 && feature!=(uint32)(-1) ) {//single 1MM match, no exact matches to this CB + stats.V[stats.noMMtoWLwithoutExact]++; + continue; + }; -void SoloReadFeature::inputRecords(uint32 **cbP, uint32 *cbReadCountExactTotal) -{ - {//load exact matches - strU_0->flush(); - strU_0->seekg(0,ios::beg); - uint32 feature, umi; - int64 cb; - while (inputFeatureUmi(strU_0, featureType, feature, umi, P.sjAll)) { - *strU_0 >> cb; if (!pSolo.cbWLyes) //if no-WL, the full cbInteger was recorded - now has to be placed in order - cb=binarySearchExact(cb,pSolo.cbWL.data(),pSolo.cbWL.size()); - if (feature != (uint32)(-1)){ + cb=binarySearchExact(cb, pSolo.cbWL.data(), pSolo.cbWLsize); + + //record feature ingle-number feature + if (feature != (uint32)(-1)) { cbP[cb][0]=feature; cbP[cb][1]=umi; - cbP[cb]+=2; - stats.V[stats.nExactMatch]++; - }; - }; - }; - - if (!pSolo.cbWLyes) //no WL => no mismatch check - return; - - {//1 match - strU_1->flush(); - strU_1->seekg(0,ios::beg); - uint32 cb, feature, umi; - while (inputFeatureUmi(strU_1,featureType, feature, umi, P.sjAll)) { - *strU_1 >> cb; - if (cbReadCountExactTotal[cb]>0) { - if (feature != (uint32)(-1)){ - cbP[cb][0]=feature; - cbP[cb][1]=umi; - cbP[cb]+=2; + if (readIndexYes) { + cbP[cb][2]=iread; }; - } else { - stats.V[stats.nNoExactMatch]++; + cbP[cb]+=cbPstride; + if (cbmatch==0) + stats.V[stats.yessubWLmatchExact]++; + } else if (readInfoYes) {//no feature - record readInfo + readInfo[iread].cb=cb; + readInfo[iread].umi=umi; }; - }; - }; + + } else {//multiple matches + #ifdef MATCH_CellRanger + double ptot=0.0, pmax=0.0, pin; + #else + float ptot=0.0, pmax=0.0, pin; + #endif - {//2 matches - strU_2->flush(); - strU_2->seekg(0,ios::beg); - uint32 cb=0, feature, umi, ncb; - while (inputFeatureUmi(strU_2,featureType, feature, umi, P.sjAll)) { - if (feature == (uint32) (-1)) { - strU_2->ignore((uint32) (-1),'\n');//ignore until the end of the line - continue; //nothing to record - }; - *strU_2 >> ncb; - float ptot=0.0,pmax=0.0; - for (uint32 ii=0; ii> cbin >> qin; - if (cbReadCountExactTotal[cbin]>0) {//otherwise this cbin does not work + *streamReads >> cbin >> qin; + if (cbReadCountTotal[cbin]>0) {//otherwise this cbin does not work qin -= pSolo.QSbase; qin = qin < pSolo.QSmax ? qin : pSolo.QSmax; - pin=cbReadCountExactTotal[cbin]*std::pow(10.0,-qin/10.0); + pin=cbReadCountTotal[cbin]*std::pow(10.0,-qin/10.0); ptot+=pin; if (pin>pmax) { cb=cbin; @@ -89,12 +72,22 @@ void SoloReadFeature::inputRecords(uint32 **cbP, uint32 *cbReadCountExactTotal) }; }; if (ptot>0.0 && pmax>=pSolo.cbMinP*ptot) { - cbP[cb][0]=feature; - cbP[cb][1]=umi; - cbP[cb]+=2; - } else { - stats.V[stats.nTooMany]++; + //record feature single-number feature + if (feature != (uint32)(-1)) { + cbP[cb][0]=feature; + cbP[cb][1]=umi; + if (readIndexYes) { + cbP[cb][2]=iread; + }; + cbP[cb]+=cbPstride; + } else if (readInfoYes) {//no feature - record readInfo + readInfo[iread].cb=cb; + readInfo[iread].umi=umi; + }; + } else if (feature != (uint32)(-1)) { + stats.V[stats.noTooManyWLmatches]++; }; }; }; }; + diff --git a/source/SoloReadFeature_record.cpp b/source/SoloReadFeature_record.cpp index 87c39601..97416bcb 100755 --- a/source/SoloReadFeature_record.cpp +++ b/source/SoloReadFeature_record.cpp @@ -1,88 +1,210 @@ #include "SoloReadFeature.h" #include "serviceFuns.cpp" #include "SequenceFuns.h" +#include "ReadAnnotations.h" +#include "SoloReadBarcode.h" -uint32 outputReadCB(fstream *streamOut, int32 featureType, uint32 umiB, uint32 gene, vector> &readSJs, const string &stringCB) -{ - if (featureType==0 || featureType==2) {//genes - *streamOut << umiB <<' '<< gene <<' '<< stringCB <<'\n'; - return 1; - } else if (featureType==1) {//sjs - for (auto &sj : readSJs) { - *streamOut << umiB <<' '<< sj[0] <<' '<< sj[1] <<' '<< stringCB <<'\n'; - }; - return readSJs.size(); - }; - - return 0; //this should not happen +class ReadSoloFeatures { +public: + uint32 gene; + vector geneMult; + vector> sj; + bool sjAnnot; + uint32 indAnnotTr; //index of the annotated transcript + Transcript **alignOut; }; -void SoloReadFeature::record(SoloReadBarcode &soloBar, uint nTr, set &readGene, set &readGeneFull, Transcript *alignOut) +uint32 outputReadCB(fstream *streamOut, const uint64 iRead, const int32 featureType, SoloReadBarcode &soloBar, const ReadSoloFeatures &reFe, const ReadAnnotations &readAnnot); + +void SoloReadFeature::record(SoloReadBarcode &soloBar, uint nTr, Transcript **alignOut, uint64 iRead, ReadAnnotations &readAnnot) { if (pSolo.type==0 || soloBar.cbMatch<0) return; + + ReadSoloFeatures reFe; + reFe.alignOut=alignOut; + reFe.indAnnotTr = 0; - //unmapped - if (nTr==0) { - stats.V[stats.nUnmapped]++; - return; - }; + uint32 nFeat=0; //number of features in this read (could be >1 for SJs) + if (nTr==0) {//unmapped + stats.V[stats.noUnmapped]++; + + } else { + switch (featureType) { + case SoloFeatureTypes::Gene : + case SoloFeatureTypes::GeneFull : + case SoloFeatureTypes::GeneFull_Ex50pAS : + case SoloFeatureTypes::GeneFull_ExonOverIntron : + { + auto *readGe = &readAnnot.annotFeatures[featureType].fSet; - vector> readSJs; - - set *readGe; - if (featureType==0) { - readGe = &readGene; - } else if (featureType==2) { - readGe = &readGeneFull; - }; + if (soloBar.pSolo.type==soloBar.pSolo.SoloTypes::SmartSeq) { + for (uint32 itr=0; itr 0) { + reFe.indAnnotTr = itr; + break;//indAnnotTr is the first genic align, and is used for Smart-seq deduplication, below in outputReadCB() + //TODO this may need to be fixed for Smart-seq multimappers + }; + }; + }; + + if (readGe->size()==0) {//check genes + stats.V[stats.noNoFeature]++;//no gene + } else if (readGe->size()>1) { + stats.V[stats.yesWLmatch_MultiFeature]++;//multi-gene reads + if (nTr>1) + stats.V[stats.yessubWLmatch_MultiFeatureMultiGenomic]++;//multigene caused by multimapper + + if (pSolo.multiMap.yes.multi) {//output multimappers + reFe.geneMult.resize(readGe->size()); + uint32 ii=0; + for (auto &g: *readGe) {//set high bit to mark multimappers + reFe.geneMult[ii] = g | geneMultMark; + ++ii; + }; + + nFeat = outputReadCB(streamReads, iRead, featureType, soloBar, reFe, readAnnot); + }; + } else {//unique-gene reads + reFe.gene = *readGe->begin(); + nFeat = outputReadCB(streamReads, (readIndexYes ? iRead : (uint64)-1), featureType, soloBar, reFe, readAnnot); + }; + }; + break; + + case SoloFeatureTypes::SJ : + if (nTr>1) {//reject all multimapping junctions + stats.V[stats.yessubWLmatch_MultiFeatureMultiGenomic]++; + //} else if (readAnnot.geneConcordant.size()>1){//for SJs, still check genes, no feature if multi-gene + // stats.V[stats.yesWLmatch_MultiFeature]++; + } else {//one gene or no gene + alignOut[0]->extractSpliceJunctions(reFe.sj, reFe.sjAnnot); + //if ( reFe.sj.empty() || (reFe.sjAnnot && readAnnot.geneConcordant.size()==0) ) {//no junctions, or annotated junction but no gene (i.e. read does not fully match transcript) + if ( reFe.sj.empty() ) { + stats.V[stats.noNoFeature]++; + } else {//good junction + nFeat = outputReadCB(streamReads, (readIndexYes ? iRead : (uint64)-1), featureType, soloBar, reFe, readAnnot); + }; + }; + break; + + case SoloFeatureTypes::Transcript3p : + if (readAnnot.transcriptConcordant.size()==0 || soloBar.cbMatch>1) {//do not record ambiguous CB + stats.V[stats.noNoFeature]++; + } else { + nFeat = outputReadCB(streamReads, iRead, featureType, soloBar, reFe, readAnnot); + }; + if (readAnnot.transcriptConcordant.size()==1 && readAnnot.transcriptConcordant[0][1] < transcriptDistCount.size()) { + //read maps to one transcript - use for distTTS distribution function + transcriptDistCount[readAnnot.transcriptConcordant[0][1]]++; + }; + + break; - if (featureType==0 || featureType==2) {//genes - //check genes, return if no gene of multimapping - if (readGe->size()==0) { - stats.V[stats.nNoFeature]++; - return; - }; - if (readGe->size()>1) { - stats.V[stats.nAmbigFeature]++; - if (nTr>1) - stats.V[stats.nAmbigFeatureMultimap]++; - return; - }; - } else if (featureType==1) {//SJs - if (nTr>1) {//reject all multimapping junctions - stats.V[stats.nAmbigFeatureMultimap]++; - return; - }; + case SoloFeatureTypes::Velocyto : + //different record: iRead, nTr, tr1, type1, tr2, type2 ... + if (readAnnot.trVelocytoType.size()>0) {//otherwise, no gene + + sort(readAnnot.trVelocytoType.begin(), readAnnot.trVelocytoType.end(), + [](const trTypeStruct &t1, const trTypeStruct &t2) {return t1.tr < t2.tr;}); - //for SJs, still check genes, return if multi-gene - if (readGene.size()>1) { - stats.V[stats.nAmbigFeature]++; - return; - }; - bool sjAnnot; - alignOut->extractSpliceJunctions(readSJs, sjAnnot); - if ( readSJs.empty() || (sjAnnot && readGene.size()==0) ) {//no junctions, or annotated junction buy no gene (i.e. read does not fully match transcript) - stats.V[stats.nNoFeature]++; - return; - }; + *streamReads << iRead <<' '<< readAnnot.trVelocytoType.size(); + for (auto &tt: readAnnot.trVelocytoType) + *streamReads <<' '<< tt.tr <<' '<< (uint32) tt.type; + *streamReads <<'\n'; + nFeat=1; + } else { + stats.V[stats.noNoFeature]++; + }; + break; //no need to go with downstream processing + + };//switch (featureType) + };//if (nTr==0) + + if (nFeat==0 && readInfoYes) {//no feature, but readInfo requested + outputReadCB(streamReads, iRead, (uint32)-1, soloBar, reFe, readAnnot); }; - - if (soloBar.cbMatch==0) {//exact match - uint32 n1 = outputReadCB(strU_0, featureType, soloBar.umiB, *readGe->begin(), readSJs, to_string(soloBar.cbI)); - if (pSolo.cbWL.size()>0) {//WL - cbReadCount[soloBar.cbI] += n1; - } else {//no WL - cbReadCountMap[soloBar.cbI] += n1; - }; - return; - } else if (soloBar.cbMatch==1) {//1 match with 1MM - cbReadCount[soloBar.cbI]+= outputReadCB(strU_1, featureType, soloBar.umiB, *readGe->begin(), readSJs, to_string(soloBar.cbI)); - return; - } else {//>1 matches - uint32 nfeat=outputReadCB(strU_2, featureType, soloBar.umiB, *readGe->begin(), readSJs, to_string(soloBar.cbMatch) + soloBar.cbMatchString); + + if (nFeat==0) + return; //no need to record the number of reads per CB + + if (pSolo.cbWLyes) {//WL for (auto &cbi : soloBar.cbMatchInd) - cbReadCount[cbi] += nfeat; - return; + cbReadCount[cbi] += nFeat; + } else {//no WL + cbReadCountMap[soloBar.cbMatchInd[0]] += nFeat; }; + + return; +}; + +uint32 outputReadCB(fstream *streamOut, const uint64 iRead, const int32 featureType, SoloReadBarcode &soloBar, const ReadSoloFeatures &reFe, const ReadAnnotations &readAnnot) +{ + /*format of the temp output file + * UMI [iRead] type feature* cbMatchString + * 0=exact match, 1=one non-exact match, 2=multipe non-exact matches + * gene or sj[0] sj[1] + * CB or nCB {CB Qual, ...} + */ + + if (soloBar.pSolo.type==soloBar.pSolo.SoloTypes::SmartSeq && featureType!=-1) {//need to calculate "UMI" from align start/end + soloBar.umiB=reFe.alignOut[reFe.indAnnotTr]->chrStartLengthExtended(); + }; + + uint64 nout=1; + + switch (featureType) { + case -1 : + //no feature, output for readInfo + *streamOut << soloBar.umiB <<' '<< iRead <<' '<< -1 <<' '<< soloBar.cbMatch <<' '<< soloBar.cbMatchString <<'\n'; + break; + + case SoloFeatureTypes::Gene : + case SoloFeatureTypes::GeneFull : + case SoloFeatureTypes::GeneFull_Ex50pAS : + case SoloFeatureTypes::GeneFull_ExonOverIntron : + if (reFe.geneMult.size()==0) { + //just gene id + *streamOut << soloBar.umiB <<' ';//UMI + if ( iRead != (uint64)-1 ) + *streamOut << iRead <<' ';//iRead + *streamOut << reFe.gene <<' '<< soloBar.cbMatch <<' '<< soloBar.cbMatchString <<'\n';; + } else { + for (auto &g : reFe.geneMult) { + *streamOut << soloBar.umiB <<' ';//UMI + *streamOut << iRead <<' ';//iRead is always output for multiGene + *streamOut << g <<' '<< soloBar.cbMatch <<' '<< soloBar.cbMatchString <<'\n';; + }; + nout = reFe.geneMult.size(); + }; + break; + + case SoloFeatureTypes::SJ : + //sj - two numbers, multiple sjs per read + for (auto &sj : reFe.sj) { + *streamOut << soloBar.umiB <<' ';//UMI + if ( iRead != (uint64)-1 ) + *streamOut << iRead <<' ';//iRead + *streamOut << sj[0] <<' '<< sj[1] <<' '<< soloBar.cbMatch <<' '<< soloBar.cbMatchString <<'\n'; + }; + nout=reFe.sj.size(); + break; + + case SoloFeatureTypes::Transcript3p : + //transcript,distToTTS structure + *streamOut << soloBar.cbMatchString <<' '; + *streamOut << soloBar.umiB <<' '; + *streamOut << readAnnot.transcriptConcordant.size(); + for (auto &tt: readAnnot.transcriptConcordant) { + *streamOut <<' '<< tt[0] <<' '<< tt[1]; + }; + if ( iRead != (uint64)-1 ) + *streamOut <<' '<< iRead;//iRead + *streamOut <<'\n'; + nout=1; + + break; + }; //switch (featureType) + + return nout; }; diff --git a/source/SoloRead_record.cpp b/source/SoloRead_record.cpp index ed4cff31..6386ef47 100755 --- a/source/SoloRead_record.cpp +++ b/source/SoloRead_record.cpp @@ -1,10 +1,12 @@ #include "SoloRead.h" -void SoloRead::record(uint64 nTr, set &readGene, set &readGeneFull, Transcript *alignOut) +void SoloRead::record(uint64 nTr, Transcript **alignOut, uint64 iRead, ReadAnnotations &readAnnot) { - if (pSolo.type==0) + if (pSolo.type==pSolo.SoloTypes::None) + return; + if (pSolo.type==pSolo.SoloTypes::CB_samTagOut) return; for (uint32 ii=0; iirecord(*readBar, nTr, readGene, readGeneFull, alignOut); + readFeat[ii]->record(*readBar, nTr, alignOut, iRead, readAnnot); }; diff --git a/source/SpliceGraph.cpp b/source/SpliceGraph.cpp new file mode 100755 index 00000000..badcae4a --- /dev/null +++ b/source/SpliceGraph.cpp @@ -0,0 +1,33 @@ +/* + * Created by Fahimeh Mirhaj on 6/10/19. +*/ +using namespace std; + +#include "SpliceGraph.h" +#include "GTF.h" +SpliceGraph::SpliceGraph (SuperTranscriptome &superTrome, Parameters &P, ReadAlign *RA) : superTrome(superTrome), P(P), RA(RA) +{ + //find candidate superTr + superTrSeedCount = new typeSuperTrSeedCount[2*superTrome.N];//TODO: for stranded data, do not need 2nd strand + + //Smith-Waterman + scoringMatrix = new typeAlignScore*[superTrome.sjDonorNmax+2]; + scoreTwoColumns[0] = new typeAlignScore[maxSeqLength]; + scoreTwoColumns[1] = new typeAlignScore[maxSeqLength]; + for(uint32 ii = 0; ii < superTrome.sjDonorNmax+2; ii++) { + scoringMatrix[ii] = new typeAlignScore[maxSeqLength];//TODO make it a user parameter + }; + sjDindex = new uint32[superTrome.sjDonorNmax]; + + //rowCol.reserve(100000); + //rowSJ.reserve(100000); + //blockCoord.reserve(100000); + //blockSJ.reserve(10000); +}; + +SpliceGraph::~SpliceGraph() { + for(uint i = 0; i < maxSeqLength; i++) { + delete[] scoringMatrix[i]; + }; + delete[] scoringMatrix; +}; diff --git a/source/SpliceGraph.h b/source/SpliceGraph.h new file mode 100755 index 00000000..c7835fc0 --- /dev/null +++ b/source/SpliceGraph.h @@ -0,0 +1,58 @@ +/* + * Created by Fahimeh Mirhaj on 6/14/19. +*/ + +#ifndef H_SpliceGraph +#define H_SpliceGraph +#include "GTF.h" +#include "Transcript.h" + +class ReadAlign; + +class SpliceGraph { +public: + typedef int32 typeAlignScore; + typedef uint32 typeSeqLen; + + SuperTranscriptome &superTrome; + + //vector> readAndSuperTranscript; + const static typeSeqLen maxSeqLength = 100000;//make user parameter? + typeAlignScore **scoringMatrix, *scoreTwoColumns[2]; + const static typeSeqLen maxMatrixSize = 1000000000; //1B elements in the matrix for now + uint8 directionMatrix[maxMatrixSize]; + uint32 *sjDindex; + + int8_t gapPenalty = -1; + int8_t matchScore = 1; + int8_t misMatchPenalty = -1; + + //seed-and-rank + typedef uint16 typeSuperTrSeedCount; + typeSuperTrSeedCount *superTrSeedCount; + + //output + struct { + uint32 nMap, nMM, nI, nD, nSJ; + array aStart, aEnd; + } alignInfo; + //vector> blockCoord; + //vector blockSJ; + //vector rowCol; + //vector> rowSJ; + + + + SpliceGraph(SuperTranscriptome &superTrome, Parameters &P, ReadAlign *RA); + ~SpliceGraph(); + + typeAlignScore swScoreSpliced(const char *readSeq, const uint32 readLen, const SuperTranscript &superTr, vector> &cigar); + //void swTraceBack(array &alignEnds, array &alignStarts); + void findSuperTr(const char *readSeq, const char *readSeqRevCompl, const uint32 readLen, const string &readName, Genome &mapGen); + +private: + Parameters &P; + ReadAlign *RA; +}; + +#endif diff --git a/source/SpliceGraph_findSuperTr.cpp b/source/SpliceGraph_findSuperTr.cpp new file mode 100755 index 00000000..38785ef1 --- /dev/null +++ b/source/SpliceGraph_findSuperTr.cpp @@ -0,0 +1,186 @@ +#include "SpliceGraph.h" +#include "sjAlignSplit.h" +#include "ReadAlign.h" + +void SpliceGraph::findSuperTr(const char *readSeq, const char *readSeqRevCompl, const uint32 readLen, const string &readName, Genome &mapGen) +{//find the candidate superTranscripts: seed-and-rank algorithm implemented + + //hardcoded for now + float seedCoverageThreshold = 0.02; + float seedCoverageMinToMax = 0.5; + uint32 seedMultMax = P.seedMultimapNmax; + uint32 seedSpacing = 1; + uint32 seedLen=mapGen.pGe.gSAindexNbases; //TODO: make user-definable vector seedSuperTr; + + vector seedSuperTr; + seedSuperTr.reserve(seedMultMax); + memset(superTrSeedCount,0,sizeof(superTrSeedCount[0])*2*superTrome.N); + + for (uint32 iseed=0; iseed3) {//N + continue; //no mapping for seeds with Ns + } else { + ind1 <<= 2; + ind1 += b; + }; + }; + //find seed boundaries in SA + uint64 iSA1=mapGen.SAi[mapGen.genomeSAindexStart[seedLen-1]+ind1]; // starting point for suffix array search. + if ( (iSA1 & mapGen.SAiMarkAbsentMaskC) != 0) {//prefix does not exist, skip this seed + continue; + }; + uint64 iSA2; + if (mapGen.genomeSAindexStart[seedLen-1]+ind1+1 < mapGen.genomeSAindexStart[seedLen]) {//we are not at the end of the SA + iSA2=((mapGen.SAi[mapGen.genomeSAindexStart[seedLen-1]+ind1+1] & mapGen.SAiMarkNmask) & mapGen.SAiMarkAbsentMask) - 1; + } else { + iSA2=mapGen.nSA-1; + }; + + if (iSA2-iSA1>=seedMultMax) //this seed map too many times + continue; + + seedSuperTr.clear(); + seedSuperTr.resize(iSA2-iSA1+1); + for (uint64 isa=iSA1;isa<=iSA2;isa++) {//loop through seed SA boundaries + uint64 a1 = mapGen.SA[isa]; + uint64 aStr = a1 >> mapGen.GstrandBit; + a1 = a1 & mapGen.GstrandMask; //remove strand bit + if (aStr==1) + a1 = mapGen.nGenome - (seedLen+a1); + + if (a1>=mapGen.sjGstart) {//this is sj align. Probably do not need it... + uint64 a1D, aLengthD, a1A, aLengthA, sj1; + if ( sjAlignSplit(a1, seedLen, mapGen, a1D, aLengthD, a1A, aLengthA, sj1) ) {//if align crosses the junction, replace a1 with a1D + a1=a1D; + } else { + continue;//this align does not cross the junction, no need to contine + }; + }; + + seedSuperTr[isa-iSA1]=(uint32)(aStr*superTrome.N + mapGen.chrBin[a1 >> mapGen.pGe.gChrBinNbits]); + };//loop through seed SA boundaries + + sort(seedSuperTr.begin(),seedSuperTr.end()); + uint32 su1prev=(uint32)-1; + for (auto &su1 : seedSuperTr) {//this will eliminate multiple matches of the same seed into the same suTr + if (su1!=su1prev) { + superTrSeedCount[su1]++; + su1prev=su1; + }; + }; + + };//loop through seeds + + //find max coverage + typeSuperTrSeedCount countMax=0; + //float countOverSuperTrLenMax=0; + for (uint32 ii=0; ii<2*superTrome.N; ii++) { + countMax=max(superTrSeedCount[ii], countMax); + //countOverSuperTrLenMax=max(superTrSeedCount[ii]/float(superTr.length[ii%superTr.N]), countOverSuperTrLenMax); + }; + + if (countMax=100000 || superTrome.superTrs[sutr1].length*readLen>=1000000000) {//temporary restriction: will lift after redoing the scoringMatrix + continue; + }; + + //convert into trAll + RA->trAll[nSuperTr]=RA->trArrayPointer+nSuperTr; + RA->nWinTr[nSuperTr]=1; + Transcript &trA = *RA->trAll[nSuperTr][0]; //transcript to fill + trA=*RA->trInit; + trA.Chr=sutr1; + trA.Str=str1; + + uint32 swScore = 0; + swScore = swScoreSpliced((str1==0 ? readSeq : readSeqRevCompl), readLen, superTrome.superTrs[sutr1], trA.cigar); + + //swTraceBack(alignInfo.aEnd, alignInfo.aStart); + //float(superTrSeedCount[ii])/countMax + //float(superTrSeedCount[ii])/superTr.length[sutr1]/countOverSuperTrLenMax <<'\t'<< + + cout << readName <<'\t'<< sutr1 <<'\t'<< str1 <<'\t'<< superTrome.superTrs[sutr1].length <<'\t'<< readLen <<'\t'<< float(superTrSeedCount[ii])/readLen*seedSpacing <<'\t'<< + float(superTrSeedCount[ii])/countMax <<'\t'<< + swScore <<'\t'<< float(swScore)/readLen <<'\t'<< alignInfo.aStart[0] <<'\t'<< alignInfo.aEnd[0] <<'\t'<< alignInfo.aStart[1] <<'\t'<< alignInfo.aEnd[1] << endl; + + trA.maxScore=swScore; + trA.nMatch=swScore;//TODO fix this, calculate number of matched bases + trA.nExons=0; + trA.gStart=mapGen.chrStart[trA.Chr]+alignInfo.aStart[1]; + trA.nMM=alignInfo.nMM; + trA.lIns=alignInfo.nI; + trA.lDel=alignInfo.nD; + trA.rLength=alignInfo.nMap; +// {//calculate blocks from rowCol and rowSJ +// int32 iEx=-1;//current exon +// for (uint32 row=alignInfo.aStart[0]; row<=alignInfo.aEnd[0]; row++) { +// +// if (rowCol[row]>=0) {//this row has no mapped base (i.e. no block) = bases deleted from query +// if (iEx==-1 || rowCol[row]!=rowCol[row-1]+1) {//start new block +// ++iEx; +// trA.exons[iEx][EX_R]=row; +// trA.exons[iEx][EX_G]=mapGen.chrStart[trA.Chr]+rowCol[row]; +// trA.exons[iEx][EX_L]=1; +// trA.canonSJ[iEx]=-1; +// trA.sjAnnot[iEx]=0; +// } else { +// trA.exons[iEx][EX_L]++; +// }; +// }; +// +// //this needs to be done even if rowCol[row]==-1 +// if (rowSJ[row][0]>=0) {//junction: create two 0-length blocks to encapsulate junction +// ++iEx; +// trA.exons[iEx][EX_R]=row+1; +// trA.exons[iEx][EX_G]=mapGen.chrStart[trA.Chr]+rowSJ[row][0]+1; +// trA.exons[iEx][EX_L]=0; +// trA.canonSJ[iEx]=1;//TODO actual motif +// trA.sjAnnot[iEx]=1; +// //if (rowSJ[row]!=rowCol[row+1]) {//create 0-length block to mark junction, on the next row +// ++iEx; +// trA.exons[iEx][EX_R]=row+1; +// trA.exons[iEx][EX_G]=mapGen.chrStart[trA.Chr]+rowSJ[row][1]; +// trA.exons[iEx][EX_L]=0; +// trA.canonSJ[iEx]=-1; +// trA.sjAnnot[iEx]=0; +// //}; +// }; +// }; +// +// trA.nExons=iEx+1; +// +// for (uint32 iex=0; iexmaxMaxScore) { + maxMaxScore=swScore; + RA->trBest=&trA; + }; + nSuperTr++; + }; + RA->nW=nSuperTr; + return; +}; + diff --git a/source/SpliceGraph_swScoreSpliced.cpp b/source/SpliceGraph_swScoreSpliced.cpp new file mode 100755 index 00000000..c31869be --- /dev/null +++ b/source/SpliceGraph_swScoreSpliced.cpp @@ -0,0 +1,249 @@ +/* + * Created by Fahimeh Mirhaj on 6/18/19. + */ + +#include "SpliceGraph.h" +#define macro_CompareScore(score1,scoreMax,dirInd,dirIndMax) if(score1>scoreMax){dirIndMax=dirInd;scoreMax=score1;} + +SpliceGraph::typeAlignScore SpliceGraph::swScoreSpliced + (const char *readSeq, const uint32 readLen, const SuperTranscript &superTr, vector> &cigar) +{//Smith-Waterman alignment with splices + + uint32 superTrLen = superTr.length; + + typeAlignScore scoreMaxGlobal = 0; + + int32 iDonor=0; //current donor in the donor list + int32 iAcceptor=0;//current acceptor in the sjC list (sorted by acceptors + bool sjYes=superTr.sjC.size() > 0; //spliced superTr + + typeAlignScore *scoreColumn, *scoreColumnPrev;//pointer to column and prev column + uint32 iTwoColumn = 0;//selects the column from scoreTwoColumn 2-col matrix + scoreColumn = scoreTwoColumns[iTwoColumn]; + for(uint32 ii = 0; ii <= readLen; ii++){//fill 0th column + scoreColumn[ii] = 0; + }; + + uint32 matIndex=0;//current matIndex: starting from 1st column (not 0th) + + for(uint32 col=0; col rowCol(readLen), rowSJ(readLen,0); //records col vs row TODO define outside for speed +// --iAcceptor; //= last junction +// +// rowCol.clear(); +// rowSJ.clear(); +// rowCol.resize(readLen,-1); +// rowSJ.resize(readLen+1,{-1,-1});//one extra element since we are going to check row+1 +// +// while(col >= 0 && row >= 0) { +// uint32 dir1= (uint32) directionMatrix[row+col*readLen]; +// if (dir1==0) //reached scoringMatrix==0 +// break; +// switch (dir1) +// { +// case 1: +// --row; +// ++nI; +// break; +// case 2: +// --col; +// ++nD; +// break; +// case 3: +// ++nMapped; +// nMM+=(uint32)(readSeq[row]!=superTr.seqP[col]); +// rowCol[row]=col;//for each row, point to the column where blocj starts +// --row; +// --col; +// break; +// default: //junction jump +// ++nSJ; +// while (iAcceptor+1!=0 && col <= (int32)superTr.sjC[iAcceptor][1]) {//find (acceptor-1) that matches this column +// --iAcceptor; +// }; +// //row: same or -1 +// if ((dir1-4)%2 == 1) {//diagonal-like +// ++nMapped; +// nMM+=(uint32)(readSeq[row]!=superTr.seqP[col]); +// rowCol[row]=col;//for each row, point to the column where block starts +// --row; +// } else { +// //++nD; //? +// }; +// rowSJ[row][1]=col;//acceptor +// //column: jump to donor +// col=superTr.sjDonor[ superTr.sjC[iAcceptor+1+(dir1-4)/2][2] ]; +// rowSJ[row][0]=col;//donor +// }; +// }; +// +// row=max(0,row); +// while (rowCol[row]<0) +// row++; //find first col>=0 - this is the alignment start. +// alignInfo.aStart[0]=row; +// alignInfo.aStart[1]=rowCol[row]; + + cigar.clear(); + cigar.reserve(readLen); + int32 row = alignInfo.aEnd[0];//true row + int32 col = alignInfo.aEnd[1]; + + alignInfo.nMap=0; + alignInfo.nMM=0; + alignInfo.nI=0; + alignInfo.nD=0; + alignInfo.nSJ=0; + iAcceptor=superTr.sjC.size()-1; //= last junction + + if (row!=(int32)readLen-1) //soft-clip + cigar.push_back({BAM_CIGAR_S, readLen-1-row}); + + uint32 cigarOp=0, cigarLen=0, cigarOpPrev=(uint32)-1; + uint32 sjGap=0; + while(col >= 0 && row >= 0) { + uint32 dir1= (uint32) directionMatrix[row+col*readLen]; + + if (dir1==0) //reached scoringMatrix==0 + break; + + switch (dir1) + { + case 1: + --row; + alignInfo.nI++; + cigarOp=BAM_CIGAR_I; + break; + case 2: + --col; + alignInfo.nD++; + cigarOp=BAM_CIGAR_D; + break; + case 3: + alignInfo.nMap++; + alignInfo.nMM += (uint32)(readSeq[row]!=superTr.seqP[col]); + cigarOp=BAM_CIGAR_M; + --row; + --col; + break; + default: //junction jump + alignInfo.nSJ++; + while (iAcceptor+1!=0 && col <= (int32)superTr.sjC[iAcceptor][1]) {//find (acceptor-1) that matches this column + --iAcceptor; + }; + + //row: same or -1 + if ((dir1-4)%2 == 1) {//diagonal-like + alignInfo.nMap++; + alignInfo.nMM+=(uint32)(readSeq[row]!=superTr.seqP[col]); + --row; + cigarOp=BAM_CIGAR_M; + } else { + alignInfo.nD++; + cigarOp=BAM_CIGAR_D; + }; + + //column: jump to donor + sjGap=col; + col=superTr.sjDonor[ superTr.sjC[iAcceptor+1+(dir1-4)/2][2] ]; + sjGap=sjGap-col-1; + }; + + if (cigarOp!=cigarOpPrev) {//changed direction - record new cigar op + if (cigarLen>0) + cigar.push_back({cigarOpPrev, cigarLen}); + cigarLen=0; + cigarOpPrev=cigarOp; + }; + ++cigarLen; + if (sjGap>0) { + cigar.push_back({cigarOp, cigarLen});//record previous opeartion + cigar.push_back({BAM_CIGAR_N, sjGap});//record N + cigarLen=0; //keep cigarLen=0: after SJ, the blocks start anew + cigarOpPrev=(uint32)-1; + sjGap=0; + }; + }; + + if (cigarLen>0) + cigar.push_back({cigarOp, cigarLen}); + +// row=max(0,row); +// col=max(0,col); + + ++row; + ++col; + alignInfo.aStart[0]=row; + alignInfo.aStart[1]=col; + if (row>0) + cigar.push_back({BAM_CIGAR_S, (uint32)row}); + + std::reverse(cigar.begin(), cigar.end()); + return scoreMaxGlobal; +}; + diff --git a/source/SpliceGraph_swTraceBack.cpp b/source/SpliceGraph_swTraceBack.cpp new file mode 100755 index 00000000..595d6d7d --- /dev/null +++ b/source/SpliceGraph_swTraceBack.cpp @@ -0,0 +1,19 @@ +//#include "SpliceGraph.h" + +//void SpliceGraph::swTraceBack(array &alignEnds, array &alignStarts) +//{ + +// uint32 row = alignEnds[0]; +// uint32 col = alignEnds[1]; +// uint32 rowT = 0; +// uint32 colT = 0; +// while(col > 0 && row > 0 && scoringMatrix[col][row] != 0) { +// rowT = directionMatrix[col][row].second; +// colT = directionMatrix[col][row].first; +// +// row = rowT; +// col = colT; +// }; +// alignStarts[0]=row; +// alignStarts[1]=col; +//}; diff --git a/source/Stats.cpp b/source/Stats.cpp index e9c136e2..325e8d4e 100644 --- a/source/Stats.cpp +++ b/source/Stats.cpp @@ -11,7 +11,6 @@ void Stats::resetN() {//zero all counters for (uint ii=0; ii outType, const string commStr, const string outStr);// write commented lines to text files with stats + + void qualHistCalc(const uint64 imate, const char* qual, const uint64 len); + //void qualHistCalcSolo(const uint64 imate, const char* qual, const vector stlen); }; #endif diff --git a/source/SuperTranscriptome.cpp b/source/SuperTranscriptome.cpp new file mode 100755 index 00000000..86aeb624 --- /dev/null +++ b/source/SuperTranscriptome.cpp @@ -0,0 +1,92 @@ +#include "SuperTranscriptome.h" +#include "streamFuns.h" + +void SuperTranscriptome::sjCollapse() +{//sort junctions by superTranscript, and then by the end coordinate, and then by the start coordinate + sort(sj.begin(), sj.end(), + [](const sjInfo &sj1, const sjInfo &sj2) { + return ( sj1.super < sj2.super) || + ( sj1.super == sj2.super && sj1.start < sj2.start ) || + ( sj1.super == sj2.super && sj1.start == sj2.start && sj1.end < sj2.end ) ; + }); + + //collapse junctions in each superTr, those junctions that belong to different transcript - remove the transcript info + vector>> sjCollapsed; + sjCollapsed.resize(seq.size()); + for(uint32 i = 0; i < sj.size(); i++) { + if (i==0 || sj[i].start!=sj[i-1].start || sj[i].end!=sj[i-1].end || sj[i].super!=sj[i-1].super) //new junction + sjCollapsed[ sj[i].super ].push_back({sj[i].start, sj[i].end}); + }; + + ofstream & superTrSJstream = ofstrOpen(P.pGe.gDir+"/superTranscriptSJcollapsed.tsv", ERROR_OUT, P); + for(uint64 i = 0; i < sjCollapsed.size(); i++) { + for(auto &sj1 : sjCollapsed[i]) + superTrSJstream << i <<"\t"<< sj1[0] <<"\t"<< sj1[1] << "\n"; + }; + superTrSJstream.close(); + + P.inOut->logMain << "Number of splice junctions in superTranscripts = " << sj.size() <logMain << "Number of collapsed splice junctions in superTranscripts = " << sjCollapsed.size() < &chrStart, vector &chrLength) +{//load superTranscript seqs and + N=chrLength.size(); + superTrs.resize(N); + for (uint32 ii=0; ii> sjC1; + sjNmax=0; + sjDonorNmax=0; + vector sjDonor1; + + while(true) {//load junctions, assume they are sorted by donor coordinate + + superTrSJstream >> sutr; + bool inGood = superTrSJstream.good(); + + if (sutr!=sutr1 || !inGood) {//new suTr + //sort sj1 by acceptor position + sort(sjC1.begin(), sjC1.end(), + [](const array &sj1, const array &sj2) { + return ( sj1[1] < sj2[1] ) || + ( sj1[1] == sj2[1] && sj1[0] < sj2[0] ); + }); + + superTrs[sutr1].sjC=sjC1; + superTrs[sutr1].sjDonor=sjDonor1; + + if (sjNmax < sjC1.size()) + sjNmax=sjC1.size(); + if (sjDonorNmax < sjDonor1.size()) { + sjDonorNmax=sjDonor1.size(); + }; + + sjC1.clear(); + sjDonor1.clear(); + sutr1=sutr; + + if (!inGood) { + break; //end of file + }; + }; + + uint32 sjd, sja; + superTrSJstream >> sjd >> sja; + + if (sjDonor1.empty() || sjDonor1.back() < sjd) + sjDonor1.push_back(sjd); + + sjC1.push_back({sjd,sja,(uint32)sjDonor1.size()-1});//record donor, acceptor, and position of the donor in sjDonor + }; + superTrSJstream.close(); + + P.inOut->logMain << "Max number of splice junctions in a superTranscript = " << sjNmax <logMain << "Max number of donor sites in a superTranscript = " << sjDonorNmax <> sjC;//collapsed junctions + vector sjDonor;//SJ donor coordinates, sorted +}; + + +class SuperTranscriptome { + private: + Parameters &P; +public: + vector seqConcat;//concatenated sequences of supertranscripts, a.k.a. Condensed Genome + vector> seq;//sequences of supertranscripts + vector trIndex;//superTr's index this tr belongs to + vector> trStartEnd;//tr start/end in the superTr it belongs to + vector sj;//all junctions + + vector superTrs; + uint32 sjNmax, sjDonorNmax;//max number of SJs per superTr, SJ donors + uint32 N; //number of superTr + + + SuperTranscriptome(Parameters &P) : P(P) {}; + void sjCollapse(); + void load(char *G, vector &chrStart, vector &chrLength); +}; +#endif diff --git a/source/Test.hpp b/source/Test.hpp new file mode 100644 index 00000000..ee0d37d2 --- /dev/null +++ b/source/Test.hpp @@ -0,0 +1,13 @@ +// +// Test.hpp +// +// +// Created by Fahimeh Mirhaj on 6/18/19. +// + +#ifndef Test_hpp +#define Test_hpp + +#include + +#endif /* Test_hpp */ diff --git a/source/Transcript.cpp b/source/Transcript.cpp index d7f63b5d..81b2f1ca 100644 --- a/source/Transcript.cpp +++ b/source/Transcript.cpp @@ -50,3 +50,10 @@ void Transcript::extractSpliceJunctions(vector> &sjOut, bool &an }; }; +uint64 Transcript::chrStartLengthExtended() +{ + uint64 start1 = cStart - exons[0][EX_R]; + uint64 length1 = exons[nExons-1][EX_G] + Lread - exons[nExons-1][EX_R] - exons[0][EX_G] + exons[0][EX_R]; + + return (start1 << 32) | length1; +}; diff --git a/source/Transcript.h b/source/Transcript.h old mode 100644 new mode 100755 index 14c0b284..9b75975c --- a/source/Transcript.h +++ b/source/Transcript.h @@ -5,17 +5,20 @@ #include "Parameters.h" #include "Variation.h" #include "Genome.h" +#include class Transcript { public: uint exons[MAX_N_EXONS][EX_SIZE]; //coordinates of all exons: r-start, g-start, length + vector > cigar; //new way to record alignments, with CIGAR operations. For now, only used by splice-graph + uint shiftSJ[MAX_N_EXONS][2]; //shift of the SJ coordinates due to genomic micro-repeats int canonSJ[MAX_N_EXONS]; //canonicity of each junction uint8 sjAnnot[MAX_N_EXONS]; //anotated or not uint8 sjStr[MAX_N_EXONS]; //strand of the junction - uint intronMotifs[3]; uint8 sjMotifStrand; + bool sjYes; uint nExons; //number of exons in the read transcript @@ -31,7 +34,8 @@ class Transcript { //loci uint rStart, roStart, rLength, gStart, gLength, cStart; //read, original read, and genomic start/length, chromosome start uint Chr,Str,roStr; //chromosome and strand and original read Strand - + uint32 haploType; //haplotype index for diploid genome + bool primaryFlag; uint nMatch;//min number of matches @@ -52,6 +56,9 @@ class Transcript { vector varInd; vector varGenCoord, varReadCoord ; vector varAllele; + + //annotations + std::set alignGenes; Transcript(); //resets to 0 void reset(); //reset to 0 @@ -61,8 +68,13 @@ class Transcript { intScore alignScore(char **Read1, char *G, Parameters &P); int variationAdjust(const Genome &mapGen, char *R); string generateCigarP(); //generates CIGAR - void peOverlapSEtoPE(uint* mSta, Transcript &t); + void peOverlapSEtoPE(uint* mSta, const Transcript &t); void extractSpliceJunctions(vector> &sjOut, bool &annotYes); + + uint64 chrStartLengthExtended(); + + bool transformGenome(Genome &genOut, Transcript & A); + bool convertGenomeCigar(Genome &genOut, Transcript & A); private: diff --git a/source/Transcript_alignScore.cpp b/source/Transcript_alignScore.cpp index 9fd40ea2..4f5a9c6b 100644 --- a/source/Transcript_alignScore.cpp +++ b/source/Transcript_alignScore.cpp @@ -5,6 +5,10 @@ intScore Transcript::alignScore(char **Read1, char *G, Parameters &P) {//re-calc maxScore=0; nMM=0; nMatch=0; + + if (nExons==0) + return maxScore; + char* R=Read1[roStr==0 ? 0:2]; for (uint iex=0;iex {gStart,0,0}, + [](const array &t1, const array &t2) + { + return t1[0] < t2[0]; + }); + --cBit; + + uint64 icB = cBit-coBl.begin(); + + A.gStart=gStart-coBl[icB][0]+coBl[icB][2]; + + A.cigar.clear(); + A.cigar.reserve(cigar.size()+100); //add 100 for junctions + + uint64 gEnd=gStart;//gEnd is end+1 + //uint32 l1=0, l2=0; + //uint32 gGapNew=0; + for (uint32 iC=0; iCgStart1) + A.cigar.push_back({ cc[0], (uint32) (gEnd-gStart1) }); + + //if(cc[0]==BAM_CIGAR_M) + // l2 += gEnd-gStart1; + //if (l1!=l2) { + // cout << l1 <<" "<< l2 < nOp={0,0,0,0,0}; + for (auto c1=A.cigar.begin(); c1!=A.cigar.end(); c1++) { + nOp[(*c1)[0]] += (*c1)[1]; + if ( (*c1)[0] == BAM_CIGAR_M ) { + if (nOp[BAM_CIGAR_M] >= genOut.P.alignSJDBoverhangMin) //TODO Transcript class should have P + break; //overhang is long enough + } else if ( (*c1)[0]==BAM_CIGAR_N ) {//short overhang for this junction + //find the next M + c1++; + while ( (*c1)[0]!=BAM_CIGAR_M ) { + nOp[(*c1)[0]] += (*c1)[1]; + c1++; + }; + //remove junction + A.cigar.erase(A.cigar.begin(), c1-1);//keep one element at the beginning to convert it to S + A.cigar.at(0)={BAM_CIGAR_S, nOp[BAM_CIGAR_M]+nOp[BAM_CIGAR_S]+nOp[BAM_CIGAR_I]}; + A.gStart += nOp[BAM_CIGAR_M]+nOp[BAM_CIGAR_D]+nOp[BAM_CIGAR_N]; + break; + }; + }; + }; + + {//remove terminal junctions with too short overhangs + //TODO: loop over until all such junctions are removed + array nOp={0,0,0,0,0}; + for (auto c1=A.cigar.end()-1; c1!=A.cigar.begin(); c1--) { + nOp[(*c1)[0]] += (*c1)[1]; + if ( (*c1)[0] == BAM_CIGAR_M ) { + if (nOp[BAM_CIGAR_M] >= genOut.P.alignSJDBoverhangMin) //TODO Transcript class should have P + break; //overhang is long enough + } else if ( (*c1)[0]==BAM_CIGAR_N ) {//short overhang for this junction + //find the next M + c1--; + while ( (*c1)[0]!=BAM_CIGAR_M ) { + nOp[(*c1)[0]] += (*c1)[1]; + c1--; + }; + //remove junction + A.cigar.erase(c1+1, A.cigar.end()); + A.cigar.push_back({BAM_CIGAR_S, nOp[BAM_CIGAR_M]+nOp[BAM_CIGAR_S]+nOp[BAM_CIGAR_I]}); + break; + }; + }; + }; + + //TODO: also need to recalculate nMM + A.gLength=0; + for (const auto &cc : A.cigar) + if (cc[0]==BAM_CIGAR_M || cc[0]==BAM_CIGAR_D || cc[0]==BAM_CIGAR_N) + A.gLength += cc[1]; + + A.Str = Str; + if (A.gStart >= genOut.genomeOut.nMinusStrandOffset) {//convert to +strand + A.Str = 1-A.Str; + A.gStart = 2*genOut.genomeOut.nMinusStrandOffset - (A.gStart+A.gLength); + std::reverse(A.cigar.begin(), A.cigar.end()); + }; + + A.Chr = genOut.chrBin[A.gStart >> genOut.pGe.gChrBinNbits]; + + return (true); //conversion is always possible +}; diff --git a/source/Transcript_generateCigarP.cpp b/source/Transcript_generateCigarP.cpp index 9e7c3ca1..4879e19e 100644 --- a/source/Transcript_generateCigarP.cpp +++ b/source/Transcript_generateCigarP.cpp @@ -9,7 +9,7 @@ string Transcript::generateCigarP() stringstream samStreamCIGAR; uint leftMate=0; - if (readNmates>1) leftMate=Str; + if (readNmates>1) leftMate=Str; //not readNends: this is alignment uint trimL=exons[0][EX_R] - (exons[0][EX_R]0) { diff --git a/source/Transcript_transformGenome.cpp b/source/Transcript_transformGenome.cpp new file mode 100644 index 00000000..feffd244 --- /dev/null +++ b/source/Transcript_transformGenome.cpp @@ -0,0 +1,167 @@ +#include "Transcript.h" +#include "binarySearch2.h" + +bool Transcript::transformGenome(Genome &genOut, Transcript & A) +{ + uint32 nB=0;//number of out blocks + auto &coBl=genOut.genomeOut.convBlocks; + + //uint64 icb=0; + + //auto cBit=coBl.begin(); + for (uint32 iA=0; iA g1array = {g1,0,0}; + auto cBit=coBl.begin(); //TODO might reuse previous value of cBit, but need to take care of overlapping mates + cBit = std::upper_bound(cBit, coBl.end(), g1array, + [](const array &t1, const array &t2) + { + return t1[0] < t2[0]; + }); + + --cBit;//upperbound finds element > value, need to step back + //icb=binarySearchStride(coBl.data(), coBl.size(), exons[iA][EX_G], icb, 3); + + + uint64 b1=(*cBit)[0]; + uint64 b2=(*cBit)[0]+(*cBit)[1]-1; + uint64 b1o=(*cBit)[2]; + + /* **********---********----******** + * b1 b2 + * ++++++++++++++++ + * g1 g2 + */ + + if (g1 <= b2 ) {//fill the first o-block + A.exons[nB][EX_iFrag]=exons[iA][EX_iFrag]; + A.exons[nB][EX_R] = r1; + A.exons[nB][EX_G] = b1o + g1 - b1; + + if (g2<=b2) {//g2 inside this c-block + A.exons[nB][EX_L]=len; + } else {//g2 is past the end of this c-block + A.exons[nB][EX_L]=b2-g1+1; + }; + ++nB; + }; + + ++cBit; + while (g2 >= (*cBit)[0]) {//until c-block start is to the right of g2 + A.exons[nB][EX_iFrag]=exons[iA][EX_iFrag]; + A.exons[nB][EX_G]=(*cBit)[2]; + A.exons[nB][EX_R]=r1+(*cBit)[0]-g1; + + if (g2 < (*cBit)[0]+(*cBit)[1]) {//g2 inside this c-block + A.exons[nB][EX_L]=g2-(*cBit)[0]+1; + } else {//g2 is past the end of this c-block + A.exons[nB][EX_L]=(*cBit)[1];//full block length + }; + ++nB; + ++cBit; + }; + --cBit; + }; + + if (nB==0) + return false; //transformation did not work + + {//merge exons w/o R/G gaps + uint32 nB1 = 1; + for ( uint32 ib=1; ib0) {//flush the gap to the left + A.exons[nB1][EX_L] += minGap; + A.exons[nB1][EX_G] -= minGap; + A.exons[nB1][EX_R] -= minGap; + }; + ++nB1; + }; + }; + nB = nB1; + }; + + A.nExons=nB; + A.Str = Str; + A.Chr = genOut.chrBin[A.exons[0][EX_G] >> genOut.pGe.gChrBinNbits]; + + {//recalculate canonSJ, sjAnnot + for (uint64 ia=0; ia=0) {//annotated + A.sjAnnot[ia] = 1; + A.canonSJ[ia] = genOut.sjdbMotif[sjdbInd]; + if (genOut.sjdbMotif[sjdbInd]==0) {//shift to match annotations + if (A.exons[ia][EX_L] <= genOut.sjdbShiftLeft[sjdbInd]) { + return false; //this align is not allowed + }; + A.exons[ia][EX_L] -= genOut.sjdbShiftLeft[sjdbInd]; + A.exons[ia+1][EX_G] -= genOut.sjdbShiftLeft[sjdbInd]; + }; + + } else {//unannotated + uint64 gapG=jE-jS+1; + uint64 gapR=A.exons[ia+1][EX_R]-A.exons[ia][EX_R]-A.exons[ia][EX_L]; + if (gapR>0) {//insertion + A.canonSJ[ia]=-2; + + } else if (gapG>=genOut.P.alignIntronMin) {//junction + A.canonSJ[ia]=0; + if ( genOut.G[jS]==2 && genOut.G[jS+1]==3 && genOut.G[jE-1]==0 && genOut.G[jE]==2 ) {//GTAG + A.canonSJ[ia]=1; + } else if ( genOut.G[jS]==1 && genOut.G[jS+1]==3 && genOut.G[jE-1]==0 && genOut.G[jE]==1 ) {//CTAC + A.canonSJ[ia]=2; + } else if ( genOut.G[jS]==2 && genOut.G[jS+1]==1 && genOut.G[jE-1]==0 && genOut.G[jE]==2 ) {//GCAG + A.canonSJ[ia]=3; + } else if ( genOut.G[jS]==1 && genOut.G[jS+1]==3 && genOut.G[jE-1]==2 && genOut.G[jE]==1 ) {//CTGC + A.canonSJ[ia]=4; + } else if ( genOut.G[jS]==0 && genOut.G[jS+1]==3 && genOut.G[jE-1]==0 && genOut.G[jE]==1 ) {//ATAC + A.canonSJ[ia]=5; + } else if ( genOut.G[jS]==2 && genOut.G[jS+1]==3 && genOut.G[jE-1]==0 && genOut.G[jE]==3 ) {//GTAT + A.canonSJ[ia]=6; + }; + + } else {//deletion + A.canonSJ[ia]=-1; + }; + }; + }; + }; + + return true; +}; + diff --git a/source/Transcriptome.cpp b/source/Transcriptome.cpp index 7240864d..5c035e1b 100755 --- a/source/Transcriptome.cpp +++ b/source/Transcriptome.cpp @@ -25,7 +25,7 @@ Transcriptome::Transcriptome (Parameters &Pin) : P(Pin){ }; geStream.close(); - if ( P.quant.trSAM.yes ) {//load exon-transcript structures + if ( P.quant.trSAM.yes || P.quant.gene.yes || P.quant.geneFull_Ex50pAS.yes ) {//load exon-transcript structures //load tr and ex info ifstream & trinfo = ifstrOpen(trInfoDir+"/transcriptInfo.tab", ERROR_OUT, "SOLUTION: utilize --sjdbGTFfile /path/to/annotantions.gtf option at the genome generation step or mapping step",P); trinfo >> nTr; @@ -37,6 +37,8 @@ Transcriptome::Transcriptome (Parameters &Pin) : P(Pin){ trStr=new uint8 [nTr]; trID.resize(nTr); trGene=new uint32 [nTr]; + trLen=new uint32 [nTr]; + for (uint32 itr=0; itr> trID[itr] >> trS[itr] >> trE[itr] >> trEmax[itr] >> str1 >> trExN[itr] >> trExI[itr] >> trGene[itr]; @@ -60,6 +62,11 @@ Transcriptome::Transcriptome (Parameters &Pin) : P(Pin){ for (uint32 iex=0; iex> exSE[2*iex] >> exSE[2*iex+1] >> exLenCum[iex]; //reading all elements one after another }; + for (uint32 ii=0;iilogMain << "Loaded exon database, nEx="<> exG.nEx; @@ -146,7 +153,7 @@ void Transcriptome::quantsOutput() { ofstream qOut(P.quant.geCount.outFile); qOut << "N_unmapped"; for (int itype=0; itypegeneCounts.nType; itype++) { - qOut << "\t" < &readTranscripts, set &readGene);//transform coordinates for all aligns from genomic in RA to transcriptomic in RAtr + uint32 quantAlign (Transcript &aG, Transcript *aTall);//transform coordinates for all aligns from genomic in RA to transcriptomic in RAtr void geneCountsAddAlign(uint nA, Transcript **aAll, vector &gene1); //add one alignment to gene counts void quantsAllocate(); //allocate quants structure void quantsOutput(); //output quantification files - void geneFullAlignOverlap(uint nA, Transcript **aAll, int32 strandType, set &geneOverlap); + void geneFullAlignOverlap(uint nA, Transcript **aAll, int32 strandType, ReadAnnotFeature &annFeat); + void geneFullAlignOverlap_ExonOverIntron(uint nA, Transcript **aAll, int32 strandType, ReadAnnotFeature &annFeat, ReadAnnotFeature &annFeatGeneConcordant); + //void geneFullAlignOverlap_CR(uint nA, Transcript **aAll, int32 strandType, ReadAnnotations &readAnnot); + void classifyAlign(Transcript **alignG, uint64 nAlignG, ReadAnnotations &readAnnot); + void alignExonOverlap(uint nA, Transcript **aAll, int32 strandType, ReadAnnotFeature &annFeat); private: Parameters &P; //normal "genomic" parameters diff --git a/source/Transcriptome_alignExonOverlap.cpp b/source/Transcriptome_alignExonOverlap.cpp new file mode 100644 index 00000000..fb49750b --- /dev/null +++ b/source/Transcriptome_alignExonOverlap.cpp @@ -0,0 +1,231 @@ +#include "Transcriptome.h" +#include "ReadAlign.h" +#include "serviceFuns.cpp" +#include "AlignVsTranscript.h" +#include "ReadAnnotations.h" +#include + +int32 alignBlocksOverlapExons(Transcript &aG, uint16 exN1, uint32 *exSE1, uint64 trStart1, bool &sjConcord); + +void Transcriptome::alignExonOverlap(uint nA, Transcript **aAll, int32 strandType, ReadAnnotFeature &annFeat) +{ + annFeat.fSet={}; + + struct GeneStrOverlapAlign { + uint32 g; + int32 ov; + uint32 ia; + uint32 exl; + bool str; + bool sjc; + }; + //vector vGeStrOvAl; + //vGeStrOvAl.reserve(256); //TODO: check if this affects speed + + + typedef array OverlapTypes; + struct GeneInfo1 { + uint32 g; + uint32 ia; + OverlapTypes ot; //overlap types, prioritized: transcriptomic + }; + vector vGeneInfo1; + vGeneInfo1.reserve(256); //TODO: check if this affects speed + OverlapTypes otAS={false,true,false,true,false}; //which OverlapTypes is antisense, it will not be counted + + for (uint32 iag=0; iag(aGstart, trS, nTr);//tr1 has the maximum transcript start such that it is still <= align start: aGstart>=trS[tr1] + if (tr1==(uint32) -1) + continue; //this alignment is outside of range of all transcripts + + ++tr1; + do {//cycle back through all the transcripts + --tr1; + if ( aGend>trE[tr1] ) //alignment end is outside of this transcript + continue; + + bool sjConcord; + int32 nOverlap = alignBlocksOverlapExons(aG, trExN[tr1], exSE+2*trExI[tr1], trS[tr1], sjConcord); + if ( nOverlap>=0 ) { + bool str1 = int(strandType==0 ? aG.Str : 1-aG.Str) == (trStr[tr1]-1); + str1 = str1 || (strandType==-1); + + int exl=0; + for (uint64 iex=0; iexexl/2, + !str1 && nOverlap>exl/2, + str1, + } + }); + + /* matches Gene + vGeneInfo1.push_back({trGene[tr1], iag, { + str1 && nOverlap==exl && sjConcord, + false, + false, + false + } + }); + */ + + /* matches GeneFull_ExonOverIntron + vGeneInfo1.push_back({trGene[tr1], iag, { + str1 && nOverlap==exl && sjConcord, + false, + false, + str1 + } + }); + */ + + /* + + bool sjann=true; + for (uint64 iex=0; iex=aGend && tr1>0); + }; + + {//prune geneFull_Ex50pAS according to priorities + /* + bool bTranscr = false; //transcriptomic + bool bExonic = false; //sense, exonic: >=50% exonic + bool bExonicAS = false; + bool bIntronic = false; //sense, intronic + for (auto &v1: vGeStrOvAl) { + if ( v1.str ) {//sense + if (v1.ov==v1.exl && v1.sjc) { + bTranscr = true; + break; //this is the highest priority + } else if (v1.ov>=v1.exl/2) { + bExonic = true; + } else { + bIntronic = true; + }; + } else if (v1.ov>=v1.exl/2) { + bExonicAS = true; + }; + }; + + + for (auto &v1: vGeneInfo1) { + if ( v1.tr ) {//sense + bTranscr = true; + break; //this is the highest priority + } else if ( v1.ex ) { + bExonic = true; + } else if ( v1.as ) { + bExonicAS = true; + } else if (v1.in) { + bIntronic = true; + }; + }; + if (bTranscr) { + for (auto &v1: vGeneInfo1) + if ( v1.tr ) + annFeat.fSet.insert(v1.g); + } else if (bExonic) { + for (auto &v1: vGeneInfo1) + if ( v1.ex ) + annFeat.fSet.insert(v1.g); + } else if (bIntronic) { + for (auto &v1: vGeneInfo1) + if ( v1.in ) + annFeat.fSet.insert(v1.g); + }; + */ + + OverlapTypes otFinal={}; + for ( auto &v1: vGeneInfo1 ) { + for ( uint32 it=0; it trEnd1) //this can happen for PE reads, when the 2nd mate protrudes to the left of the first or vice versa + return -1; + + if (rs1>=re2) {//t1 block is on the right to t2, no hope of overlap + i2++; + if (i1>0 && aG.canonSJ[i1-1]>=0) + sjConcord = false; //only 1st align block does not have to match exon start + } else if (rs2>=re1) {//t2 block is on the right to t1, no hope of overlap + i1++; + sjConcord = false; + } else {//overlap + nOverlap += min(re1,re2) - max(rs1,rs2); + + if (i1>0 && rs1!=rs2 && aG.canonSJ[i1-1]>=0 ) + sjConcord = false; + + if (i1=0 ) + sjConcord = false; + + if (re1>=re2) + i2++;//1 is on the right of 2 + if (re2>=re1) + i1++;//2 is on the right of 1 + }; + }; + return nOverlap; +}; \ No newline at end of file diff --git a/source/Transcriptome_classifyAlign.cpp b/source/Transcriptome_classifyAlign.cpp new file mode 100755 index 00000000..20a539a4 --- /dev/null +++ b/source/Transcriptome_classifyAlign.cpp @@ -0,0 +1,262 @@ +#include "Transcriptome.h" +#include "ReadAlign.h" +#include "serviceFuns.cpp" +#include "AlignVsTranscript.h" +#include "ReadAnnotations.h" +#include + +int alignToTranscript(Transcript &aG, uint64 trS1, uint16 exN1, uint32 *exSE1, uint32 *exLenCum1, array &distTrEnds) +{ + bool alignIntronic =false; + bool alignExonic =false; + bool alignSpansExonIntr =false; + bool alignSJconcordant =true; + + //we assume that align is fully contained in the transcript, i.e. alignStart>=trStart, alignEnd<=trEnd + //find exon that overlaps beginning of the read + + //TODO + //iab=0; + //distTSS=aG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1]; + //iab=aG.nExons-1; + //distTTS=trLen[tr1]-(gthaG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1]+aG.exons[iab][EX_L]); + //if trStr1==2: TTS=trLen[tr1]-TTS, TSS=trLen[tr1]-TSS + + for (uint32 iab=0, ex1=0, bS=0, bE=0, eE=0, enS=0; iab(bS, exSE1, 2*exN1, ex1)) + return -1; //bS is outside of exons for this transcript + ex1 = ex1/2;//ex1 index, with alignStart>=ex1start + } else if (aG.canonSJ[iab-1]>=0) {//splice junction + if (bEprev == eE && bS == enS) {//eE and enS are still from the old ex1 + ++ex1; //junction agrees + } else { + alignSJconcordant = false; + if (!binarySearch_leLeft(bS, exSE1, 2*exN1, ex1)) + return -1; //bS is outside of exons for this transcript + ex1 = ex1/2;//ex1 index, with alignStart>=ex1start + }; + }; + + //uint64 eS=exSE1[2*ex1]; + eE = exSE1[2*ex1+1]; + enS = ex1+1 eE) { + alignSpansExonIntr = true; + //break;//if ex/in span is detected, no need to check anything else - no true : might still have non-concordant junction + }; + alignExonic = true; + + if (iab==0) { + distTrEnds[0]=exLenCum1[ex1]+bS-exSE1[2*ex1]; + }; + distTrEnds[1] = eE - bE + ( ex1==(uint32)exN1-1 ? 0 : exSE1[2*exN1-1]-exSE1[2*exN1-2]+1 + exLenCum1[exN1-1]-exLenCum1[ex1+1] ); + + } else {//block starts in the intron + if (bE >= enS) {//block overlaps next exon + alignSpansExonIntr = true; + //break;//if ex/in span is detected, no need to check anything else + }; + alignIntronic = true; + }; + };//cycle over align blocks + + if (!alignSJconcordant) //if align has a junction, it's always checked for concordance + return -1; //even for exon/intron aligns, sjs have to be concordant, otherwise align is not consistent with this transcript model + + if (alignSpansExonIntr) { + return AlignVsTranscript::ExonIntronSpan; //align spans exon/intron boundary + + } else if (!alignIntronic) {//align is purely exonic + return AlignVsTranscript::Concordant; //align is fully exonic and concordant + + } else {//align has introns + if (alignExonic) { + return AlignVsTranscript::ExonIntron; //mixed exonic/intronic align, but no span + } else { + return AlignVsTranscript::Intron; //purely intronic align + }; + }; +}; + +int alignToTranscriptMinOverlap(Transcript &aG, uint trS1, uint32 *exSE1, uint16 exN1, uint32 minOverlapMinusOne) +{ + bool alignIntronic =false; + bool alignExonic =false; + bool alignSpansExonIntr =false; + bool alignSJconcordant =true; + + //we assume that align is fully contained in the transcript, i.e. alignStart>=trStart, alignEnd<=trEnd + //find exon that overlaps beginning of the read + + for (uint32 iab=0; iab(bS, exSE1, 2*exN1) / 2;// alignStart>=ex1start + if ((uint16)ex1==exN1-1) {//reached last exon. + //we assume that the end of align is < end of transcript was checked before this function was called + //ex1 is positive since align is entirely inside this transcript + alignExonic=true;//can only be exonic + break; + }; + + while (iab < aG.nExons-1 && aG.canonSJ[iab] > -3 && aG.canonSJ[iab] < 0) {//indel, expand the block + ++iab; + }; + + uint32 bE=(uint32) (aG.exons[iab][EX_G] - trS1 + aG.exons[iab][EX_L] - 1);//block end + + if ( bE-bS < minOverlapMinusOne ) //block is too short + continue; + + + uint32 eE = exSE1[2*ex1+1];//exon1 end + uint32 enS = exSE1[2*ex1+2];//exon2 start + uint32 enE = exSE1[2*ex1+3];//exon2 end + + //bS>=eS always + if (bS+minOverlapMinusOne <= eE) {//start is certainly in exon1 + if (bE<=eE+minOverlapMinusOne) {//end is in exon1 + alignExonic=true; + } else {//end spans into intron1 + alignSpansExonIntr = true; + }; + + } else if (bS+minOverlapMinusOne < enS) {//start is in the intron1 + if (bE>=enS+minOverlapMinusOne) {//end is certainly in exon2 or intron2 + alignSpansExonIntr = true; + } else if (bE>eE+minOverlapMinusOne) {//end is certainly in intron1 + if (enS-eE>1000000) {//if intron is too large, do not mark this align as intronic. This is to match velocyto.py logic. TODO: make it a parameter + return -1;//no intronic match since the intron is too large. This prevents large introns from swallowing small genes inside them + }; + alignIntronic=true; + };//otherwise start and end are too close to exon1 end, no call + + } else {//start is too close to the exon2 start + if (bE>enE+minOverlapMinusOne) {//end is certainly in intron2 + alignSpansExonIntr = true; + } else if (bE>=enS+minOverlapMinusOne) {//end is certainly in exon2 + alignExonic=true; + };//otherwise start and end are too close to exon2 end, no call + }; + + if (aG.sjYes && (alignIntronic || alignSpansExonIntr)) {//spliced align cannot overlap an intron + alignSJconcordant=false; + break; + }; + };//cycle over align blocks + + if (!alignSJconcordant) //if align has a junction, it's always checked for concordance + return -1; //even for exon/intron aligns, sjs have to be concordant, otherwise align is not consistent with this transcript model + + if (alignSpansExonIntr) { + return AlignVsTranscript::ExonIntronSpan; //align spans exon/intron boundary + } else if (!alignIntronic) {//align is purely exonic + return AlignVsTranscript::Concordant; //align is fully exonic and concordant + } else {//align has introns + if (alignExonic) { + return AlignVsTranscript::ExonIntron; //mixed exonic/intronic align, but no span + } else { + return AlignVsTranscript::Intron; //purely intronic align + }; + }; +}; + +void Transcriptome::classifyAlign (Transcript **alignG, uint64 nAlignG, ReadAnnotations &readAnnot) +{ + readAnnot.transcriptConcordant={}; + ReadAnnotFeature &annFeat = readAnnot.annotFeatures[SoloFeatureTypes::Gene]; + annFeat.fSet={}; + readAnnot.trVelocytoType={}; + + //array reAnn={false}; + uint32 reGe=(uint32)-2;//so that the first gene can be recorded + std::bitset reAnn; //initialized to 0 (false) + + annFeat.fAlign = {}; + annFeat.fAlign.resize(nAlignG); + for (uint iag=0; iag(aG.exons[0][EX_G], trS, nTr);//tr1 has the maximum transcript start such that it is still <= align start + if (tr1==(uint32) -1) + continue; //this alignment is outside of range of all transcripts + + uint64 aGend=aG.exons[aG.nExons-1][EX_G]+aG.exons[aG.nExons-1][EX_L]-1; //TODO: this estimate does work if 2nd mate end is < 1st mate end + + ++tr1; + do {//cycle back through all the transcripts + --tr1; + if ( aGend>trE[tr1] || + (P.pSolo.strand >= 0 && (trStr[tr1]==1 ? aG.Str : 1-aG.Str) != (uint32)P.pSolo.strand) ) //!(this transcript contains the read, and has correct strand) + continue; + + array distTrEnds; + int aStatus=alignToTranscript(aG, trS[tr1], trExN[tr1], exSE+2*trExI[tr1], exLenCum+trExI[tr1], distTrEnds); + + if (aStatus==AlignVsTranscript::Concordant) {//align conforms with the transcript + + //debug + //if (aG.nExons==1 && aG.exons[0][EX_L]+distTrEnds[0]+distTrEnds[1] != trLen[tr1]) + // cerr << aG.exons[0][EX_L]+distTrEnds[0]+distTrEnds[1] <<" "<=aGend && tr1>0); + }; + + //VelocytoSimple logic + readAnnot.geneVelocytoSimple[0]=(reGe+2==0 ? (uint32)-1 : reGe);//-2 marks no gene, convert to -1 which marks either no gene or multigene - no output + readAnnot.geneVelocytoSimple[1]=reAnn.to_ulong(); +}; diff --git a/source/Transcriptome_geneFullAlignOverlap.cpp b/source/Transcriptome_geneFullAlignOverlap.cpp index 5dd69d32..ae2a1d82 100644 --- a/source/Transcriptome_geneFullAlignOverlap.cpp +++ b/source/Transcriptome_geneFullAlignOverlap.cpp @@ -1,28 +1,54 @@ #include "Transcriptome.h" #include "serviceFuns.cpp" +#include "ReadAnnotations.h" -void Transcriptome::geneFullAlignOverlap(uint nA, Transcript **aAll, int32 strandType, set &geneOverlap) +void Transcriptome::geneFullAlignOverlap(uint nA, Transcript **aAll, int32 strandType, ReadAnnotFeature &annFeat) { - for (uint32 iA=0; iA=0; ib--) {//scan through all blocks of the alignments + for (int64 ib=a.nExons-1; ib>=0; ib--) {//scan through all blocks of the alignments - uint64 be1=a.exons[ib][EX_G]+a.exons[ib][EX_L]-1;//end of the block - gi1=binarySearch1a(be1, geneFull.s, (int32) nGe); + uint64 be1=a.exons[ib][EX_G]+a.exons[ib][EX_L]-1;//end of the block + gi1=binarySearch1a(be1, geneFull.s, (int32) nGe); - while (gi1>=0 && geneFull.eMax[gi1]>=a.exons[ib][EX_G]) {//these exons may overlap this block - if (geneFull.e[gi1]>=a.exons[ib][EX_G]) {//this gene overlaps the block - int32 str1 = geneFull.str[gi1]==1 ? a.Str : 1-a.Str; - if (strandType==-1 || strandType==str1) - geneOverlap.insert(geneFull.g[gi1]); - }; - --gi1;// go to the previous gene - }; - }; - }; + while (gi1>=0 && geneFull.eMax[gi1]>=a.exons[ib][EX_G]) {//these exons may overlap this block + if (geneFull.e[gi1]>=a.exons[ib][EX_G]) {//this gene overlaps the block + int32 str1 = geneFull.str[gi1]==1 ? a.Str : 1-a.Str; + if (strandType==-1 || strandType==str1) { + annFeat.fSet.insert(geneFull.g[gi1]); + annFeat.fAlign[iA].insert(geneFull.g[gi1]); + }; + }; + --gi1;// go to the previous gene + }; + }; + }; + + /* + for (int64 ib=a.nExons-1; ib>=0; ib--) {//scan through all blocks of the alignments + + uint64 be1=a.exons[ib][EX_G]+a.exons[ib][EX_L]-1;//end of the block + int64 gi1=binarySearch1a(be1, geneFull.s, (int32) nGe); //search block-end against gene-starts. Find last gene which still starts to the left of block-end + + while (gi1>=0 && geneFull.eMax[gi1]>=a.exons[ib][EX_G]) {//these genes may overlap this block + if (geneFull.e[gi1]>=a.exons[ib][EX_G]) {//this gene overlaps the block: gene-end is to the right of block start + int32 str1 = geneFull.str[gi1]==1 ? a.Str : 1-a.Str; + if (strandType==-1 || strandType==str1) { + annFeat.fSet.insert(geneFull.g[gi1]); + annFeat.fSetTr=iA; + }; + }; + --gi1;// go to the previous gene + }; + }; + */ + }; diff --git a/source/Transcriptome_geneFullAlignOverlap_ExonOverIntron.cpp b/source/Transcriptome_geneFullAlignOverlap_ExonOverIntron.cpp new file mode 100644 index 00000000..c8e3ae0f --- /dev/null +++ b/source/Transcriptome_geneFullAlignOverlap_ExonOverIntron.cpp @@ -0,0 +1,39 @@ +#include "Transcriptome.h" +#include "serviceFuns.cpp" +#include "ReadAnnotations.h" + +void Transcriptome::geneFullAlignOverlap_ExonOverIntron(uint nA, Transcript **aAll, int32 strandType, ReadAnnotFeature &annFeat, ReadAnnotFeature &annFeatGeneConcordant) +{ + if (annFeatGeneConcordant.fSet.size()>0) {//if concordant genes were found for this read, prioritize them over intronic overlap + annFeat = annFeatGeneConcordant; + return; + } + + //calculate overlap with introns + annFeat.fSet={}; + annFeat.fAlign = {}; + annFeat.fAlign.resize(nA); + + for (uint32 iA=0; iA(aS, geneFull.s, (int32) nGe); //search align-start against gene-starts. Find last gene which still starts to the left of align-start + + while (gi1>=0 && geneFull.eMax[gi1]>=aE) {//these genes may overlap this block + if (geneFull.e[gi1]>=aE) {//this gene contains the block: gene-end is to the right of block start + int32 str1 = geneFull.str[gi1]==1 ? a.Str : 1-a.Str; + if (strandType==-1 || strandType==str1) { + annFeat.fSet.insert(geneFull.g[gi1]); + annFeat.fAlign[iA].insert(geneFull.g[gi1]); + }; + }; + --gi1;// go to the previous gene + }; + }; +}; + + diff --git a/source/Transcriptome_quantAlign.cpp b/source/Transcriptome_quantAlign.cpp old mode 100644 new mode 100755 index 98c34698..3ac61200 --- a/source/Transcriptome_quantAlign.cpp +++ b/source/Transcriptome_quantAlign.cpp @@ -2,12 +2,12 @@ #include "ReadAlign.h" #include "serviceFuns.cpp" - int alignToTranscript(Transcript &aG, uint trS1, uint8 trStr1, uint32 *exSE1, uint32 *exLenCum1, uint16 exN1, Transcript &aT) { //find exon that overlaps beginning of the read - uint32 g1=aG.exons[0][EX_G]-trS1;//start of the transcript + uint32 g1=aG.exons[0][EX_G]-trS1;//start of the align uint32 ex1=binarySearch1(g1, exSE1, 2*exN1); + //this sholud not be possible - we check before we call this function if (ex1>=2*exN1) return 0; //align start is to the right of all exons if (ex1%2==1) {//beginning of the read >=end of an exon @@ -27,7 +27,6 @@ int alignToTranscript(Transcript &aG, uint trS1, uint8 trStr1, uint32 *exSE1, ui if (aG.exons[iab][EX_G]+aG.exons[iab][EX_L]>exSE1[2*ex1+1]+trS1+1) {//block extends past exon end return 0; }; - if (iab==0 || aG.canonSJ[iab-1]<0) { aT.exons[aT.nExons][EX_R]=aG.exons[iab][EX_R]; aT.exons[aT.nExons][EX_G]=aG.exons[iab][EX_G]-trS1-exSE1[2*ex1]+exLenCum1[ex1]; @@ -89,11 +88,11 @@ int alignToTranscript(Transcript &aG, uint trS1, uint8 trStr1, uint32 *exSE1, ui return 0; //this should not happen }; -uint32 Transcriptome::quantAlign (Transcript &aG, Transcript *aTall, vector &readTranscripts, set &readTrGenes) { +uint32 Transcriptome::quantAlign (Transcript &aG, Transcript *aTall) { uint32 nAtr=0; //number of alignments to the transcriptome //binary search through transcript starts - uint32 tr1=binarySearch1a(aG.exons[0][EX_G], trS, nTr); + uint32 tr1=binarySearch1a(aG.exons[0][EX_G], trS, nTr);//tr1 has the maximum transcript start such that it is still <= align start if (tr1==(uint32) -1) return 0; //alignment outside of range of all transcripts uint aGend=aG.exons[aG.nExons-1][EX_G]; @@ -107,16 +106,6 @@ uint32 Transcriptome::quantAlign (Transcript &aG, Transcript *aTall, vector100000) -// // cerr << distTTS <<"\t"<< trLen[tr1] << "\n"; -// }; - }; }; }; } while (trEmax[tr1]>=aGend && tr1>0); diff --git a/source/VERSION b/source/VERSION index 6fff7bf9..efb8876a 100644 --- a/source/VERSION +++ b/source/VERSION @@ -1 +1 @@ -#define STAR_VERSION "2.7.2a" +#define STAR_VERSION "dev_EoI_2.7.9a_2021-09-30" diff --git a/source/alignSmithWaterman.cpp b/source/alignSmithWaterman.cpp deleted file mode 100644 index e7b96736..00000000 --- a/source/alignSmithWaterman.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "IncludeDefine.h" -#include "Transcript.h" -// local alignment with Smith-Waterman algorithm -intSWscore alignSmithWaterman(char *R, uint rL, char *G, uint gL, \ - intSWscore pMatch, intSWscore pMismatch, intSWscore pGapOpen, intSWscore pGapExtend, \ - char* T, uint Tsize, Transcript &trA) { - - intSWscore *H=new intSWscore[rL+1]; - - uint rL1=rL+1; - if (rL1*(gL+1)>Tsize) return (intSWscore) 0; - - intSWscore *E=new intSWscore[rL1]; - - memset(H,0,sizeof(H[0])*(rL1)); - memset(E,0,sizeof(E[0])*(rL1)); - - - - intSWscore maxH=0; - uint maxHr=0, maxHg=0; - - for (uint ig=1;ig<=gL;ig++) {//cycle over colums - intSWscore F=(intSWscore) 0; - intSWscore HdiagPrev=0; - for (uint ir=1;ir<=rL;ir++) {//cycle over rows - - E[ir]=max( E[ir]-pGapExtend, H[ir]-pGapOpen ); - E[ir]=max( E[ir], (intSWscore) 0 ); - - F = max( F-pGapExtend, H[ir-1]-pGapOpen ); - F = max( F, (intSWscore) 0); - - intSWscore Hdiag = G[ig-1]==R[ir-1] ? HdiagPrev+pMatch : HdiagPrev-pMismatch; - -// if (H[ir]>E[ir] & H[ir]>F) - - HdiagPrev=H[ir]; - - if (F>Hdiag && F>E[ir]) {//insertion (gap in read) - H[ir]=F; - T[ir+ig*rL1]=1; - } else if (Hdiag>F && Hdiag>E[ir]) {//match-mismatch - H[ir]=Hdiag; - T[ir+ig*rL1]=2; - } else {//deletion (gap in genome) - H[ir]=E[ir]; - T[ir+ig*rL1]=3; - }; - - if (H[ir]<0) { - H[ir]=0; - }; - - if (H[ir]==0) { - T[ir+ig*rL1]=0; - }; - -// Hdiag=max(Hdiag,E[ir]); -// Hdiag=max(Hdiag,F); -// H[ir]=max(Hdiag,(intSWscore) 0); - - if (H[ir]>maxH) { - maxH=H[ir]; - maxHr=ir; - maxHg=ig; - }; - #ifdef DEBUG_SW - stdOut << setw(2)<0 && ir>0 && ig>0) { - if (T[ir+ig*rL1]==2) { - if (prevOper==2) {//increase length - trA.exons[trA.nExons][EX_L]++; - } else {//new exon - ++trA.nExons; - trA.exons[trA.nExons][EX_L]=1; - trA.exons[trA.nExons][EX_R]=ir; - trA.exons[trA.nExons][EX_G]=ig; - prevOper=2; - }; - --ir; - --ig; - } else if (T[ir+ig*rL1]==1) {//gap in read - --ir; - prevOper=1; - } else {//gap in genome - --ig; - prevOper=3; - }; - }; - - ++trA.nExons; - for (uint ii=0;ii=1 && ig>=1) { -// -// rMap[ir-1]=ig; -// -// }; - - return maxH; -}; diff --git a/source/alignSmithWaterman.h b/source/alignSmithWaterman.h deleted file mode 100644 index e699541b..00000000 --- a/source/alignSmithWaterman.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "IncludeDefine.h" -intSWscore alignSmithWaterman(char *R, uint rL, char *G, uint gL, intSWscore pMatch, intSWscore pMismatch, intSWscore pGapOpen, intSWscore pGapExtend, char* T, uint Tsize, Transcript &trA); diff --git a/source/bamRemoveDuplicates.cpp b/source/bamRemoveDuplicates.cpp index ef8fc649..13958d02 100644 --- a/source/bamRemoveDuplicates.cpp +++ b/source/bamRemoveDuplicates.cpp @@ -118,6 +118,11 @@ void bamRemoveDuplicates(const string bamFileName, const string bamFileNameOut, bamA=bam_init1(); BGZF *bamIn=bgzf_open(bamFileName.c_str(),"r"); + if (bamIn==NULL) { + exitWithError("EXITING because of fatal ERROR: could not open --inputBAMfile " + bamFileName + + "SOLUTION: check that file " + bamFileName + " exists and has proper read permissions." + , std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); + }; bam_hdr_t *bamHeader=bam_hdr_read(bamIn); BGZF *bgzfOut; @@ -176,7 +181,14 @@ void bamRemoveDuplicates(const string bamFileName, const string bamFileNameOut, bamA->data=((uint8_t*) bamP)+9*4+((bamP[3]<<24)>>24)+((bamP[4]<<16)>>16)*4+(bamP[5]+1)/2+bamP[5];//add length for: core, name, cigar, seq, qual bamA->l_data=((uint8_t*) bamP)+bamP[0]+1-bamA->data; - nMult=bam_aux2i(bam_aux_get(bamA,"NH")); + uint8_t *tagP = bam_aux_get(bamA,"NH"); + if (tagP==0) { + ostringstream errOut; + errOut <<"EXITING because of fatal ERROR: SAM tag NH is missing from a read, but it's required for deduplication. \n"; + errOut <<"SOLUTION: re-generate BAM file with NH and AS tags."; + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); + }; + nMult=bam_aux2i(tagP); if (nMult==1 || (nMult>1 && P.removeDuplicates.markMulti)) { @@ -199,7 +211,15 @@ void bamRemoveDuplicates(const string bamFileName, const string bamFileNameOut, uint32* bamP1=(uint32*) aD[pp*2];//pointer to the 1st mate of the pair bamA->data=((uint8_t*) bamP1)+9*4+((bamP1[3]<<24)>>24)+((bamP1[4]<<16)>>16)*4+(bamP1[5]+1)/2+bamP1[5];//add length for: core, name, cigar, seq, qual bamA->l_data=((uint8_t*) bamP1)+bamP1[0]+1-bamA->data; - int score1=bam_aux2i(bam_aux_get(bamA,"AS")); + + uint8_t *tagP = bam_aux_get(bamA,"AS"); + if (tagP==0) { + ostringstream errOut; + errOut <<"EXITING because of fatal ERROR: SAM tag AS is missing from a read, but it's required for deduplication. \n"; + errOut <<"SOLUTION: re-generate BAM file with NH and AS tags."; + exitWithError(errOut.str(), std::cerr, P.inOut->logMain, EXIT_CODE_PARAMETER, P); + }; + int score1=bam_aux2i(tagP); if (score1>bScore) { bScore=score1; bP=pp; diff --git a/source/bamSortByCoordinate.cpp b/source/bamSortByCoordinate.cpp new file mode 100644 index 00000000..edc2e951 --- /dev/null +++ b/source/bamSortByCoordinate.cpp @@ -0,0 +1,92 @@ +#include "bamSortByCoordinate.h" +#include "BAMfunctions.h" +#include "BAMbinSortByCoordinate.h" +#include "BAMbinSortUnmapped.h" +#include "ErrorWarning.h" +#include "bam_cat.h" + +void bamSortByCoordinate (Parameters &P, ReadAlignChunk **RAchunk, Genome &genome, Solo &solo) { + if (P.outBAMcoord) {//sort BAM if needed + *P.inOut->logStdOut << timeMonthDayTime() << " ..... started sorting BAM\n" <logMain << timeMonthDayTime() << " ..... started sorting BAM\n" <chunkOutBAMcoord->binTotalBytes[ibin]+24*RAchunk[it]->chunkOutBAMcoord->binTotalN[ibin]; + }; + if (binS>maxMem) maxMem=binS; + }; + P.inOut->logMain << "Max memory needed for sorting = "<P.limitBAMsortRAM) { + ostringstream errOut; + errOut <<"EXITING because of fatal ERROR: not enough memory for BAM sorting: \n"; + errOut <<"SOLUTION: re-run STAR with at least --limitBAMsortRAM " <logMain, EXIT_CODE_PARAMETER, P); + } else if(maxMem==0) { + P.inOut->logMain << "WARNING: nothing to sort - no output alignments" <logMain, EXIT_CODE_PARAMETER, P); + }; + outBAMwriteHeader(bgzfOut,P.samHeaderSortedCoord,genome.chrNameAll,genome.chrLengthAll); + bgzf_close(bgzfOut); + } else {//sort + uint totalMem=0; + #pragma omp parallel num_threads(P.outBAMsortingThreadNactual) + #pragma omp for schedule (dynamic,1) + for (uint32 ibin1=0; ibin1chunkOutBAMcoord->binTotalN[ibin]; + binS += RAchunk[it]->chunkOutBAMcoord->binTotalBytes[ibin]; + }; + + if (binS==0) continue; //empty bin + + if (ibin == nBins-1) {//last bin for unmapped reads + BAMbinSortUnmapped(ibin,P.runThreadN,P.outBAMsortTmpDir, P, genome, solo); + } else { + uint newMem=binS+binN*24; + bool boolWait=true; + while (boolWait) { + #pragma omp critical + if (totalMem+newMem < P.limitBAMsortRAM) { + boolWait=false; + totalMem+=newMem; + }; + sleep(0.1); + }; + BAMbinSortByCoordinate(ibin,binN,binS,P.runThreadN,P.outBAMsortTmpDir, P, genome, solo); + #pragma omp critical + totalMem-=newMem;//"release" RAM + }; + }; + + //concatenate all BAM files, using bam_cat + char **bamBinNames = new char* [nBins]; + vector bamBinNamesV; + for (uint32 ibin=0; ibin>mapGen.GstrandBit) == 0; //forward or reverse strand of the genome - SAstr &= mapGen.GstrandMask; - if (!dirG) SAstr=mapGen.nGenome-1-SAstr; - uint indPref1=0; - */ - for (uint iL=0; iL < mapGen.pGe.gSAindexNbases; iL++) {//calculate index - /*{//testing: old way - indPref1 <<= 2; - - uint g1= (uint) G[dirG ? SAstr+iL : SAstr-iL]; //reverese if (-) strand - - if (g1>3) {//if N, this suffix does not belong in SAi - for (uint iL1=iL; iL1 < mapGen.pGe.gSAindexNbases; iL1++) { - SAi1.writePacked(mapGen.genomeSAindexStart[iL1]+ind0[iL1],SAi[mapGen.genomeSAindexStart[iL1]+ind0[iL1]] | mapGen.SAiMarkNmaskC); - }; - } else //relying on the true code to break iL cycle - { - if (!dirG) g1=3-g1; //complement if (-) strand - - indPref1 += (uint) g1; - - if ( indPref1 > ind0a[iL] || isa==0 ) {//new && good index, record it - SAi1.writePacked(mapGen.genomeSAindexStart[iL]+indPref1, isa); - for (uint ii=ind0a[iL]+1; iilogMain, EXIT_CODE_INPUT_FILES, P); - }; - }; - }; - */ uint indPref = indFull >> (2*(mapGen.pGe.gSAindexNbases-1-iL)); -// if (indPref!=indPref1) -// cout<< iL <<" "<< isa <<" "<< indPref <<" "< ind0[iL] || isa==0 ) {//new && good index, record it - //testing -// if (funCalcSAiFromSA(G,SA,isa,iL+1,P)!=indPref) -// cout<< iL <<" "<< isa <<" "<< indPref <<" "<logMain, EXIT_CODE_INPUT_FILES, P); }; - - }; //find next index not equal to the current one funSAiFindNextIndex(G, SA, isaStep, isa, indFull, iL4, mapGen);//indFull and iL4 have been already defined at the previous step -// isa++; -// indFull=funCalcSAiFromSA(G,SA,isa,mapGen.pGe.gSAindexNbases,P,iL4); + };//isa cycle + + for (uint iL=0; iL < mapGen.pGe.gSAindexNbases; iL++) {//fill up unfilled indexes + for (uint ii=mapGen.genomeSAindexStart[iL]+ind0[iL]+1; ii0) - {//previous chr records exist + if (!flagRun && mapGen.chrLength.size()>0) {//previous chr records exist mapGen.chrStart.pop_back();//remove last record, it will be recorded again N = mapGen.chrStart.back()+mapGen.chrLength.back(); mapGen.chrLength.pop_back();//remove last record, it will be recorded again @@ -15,27 +14,25 @@ uint genomeScanFastaFiles (Parameters &P, char* G, bool flagRun, Genome &mapGen) ifstream fileIn; for (uint ii=0;iilogMain, EXIT_CODE_INPUT_FILES, P); }; char cc=fileIn.peek(); - if ( !fileIn.good() ) - {// + if ( !fileIn.good() ) {// ostringstream errOut; errOut << "EXITING because of INPUT ERROR: could not read from genomeFastaFile: " <logMain, EXIT_CODE_INPUT_FILES, P); }; - if (cc!='>') - { + if (cc!='>') { ostringstream errOut; errOut << "EXITING because of INPUT ERROR: the file format of the genomeFastaFile: " <'.\n"; errOut << " Solution: check formatting of the fasta file. Make sure the file is uncompressed (unzipped).\n"; exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); - }; while(!fileIn.eof()) {//read each file until eof + }; + while(!fileIn.eof()) {//read each file until eof string lineIn (4096,'.'); getline(fileIn,lineIn); if (lineIn[0]=='>') {//new chromosome @@ -47,7 +44,8 @@ uint genomeScanFastaFiles (Parameters &P, char* G, bool flagRun, Genome &mapGen) mapGen.chrName.push_back(chrName1); }; - if (!flagRun && mapGen.chrStart.size()>0) mapGen.chrLength.push_back(N-mapGen.chrStart.at(mapGen.chrStart.size()-1)); //true length of the chr + if (!flagRun && mapGen.chrStart.size()>0) mapGen.chrLength.push_back(N-mapGen.chrStart.back()); //true length of the chr + if (N>0) {//pad the chromosomes to bins boudnaries N = ( (N+1)/mapGen.genomeChrBinNbases+1 )*mapGen.genomeChrBinNbases; @@ -55,7 +53,9 @@ uint genomeScanFastaFiles (Parameters &P, char* G, bool flagRun, Genome &mapGen) if (!flagRun) { mapGen.chrStart.push_back(N); - P.inOut->logMain << mapGen.pGe.gFastaFiles.at(ii)<<" : chr # " << mapGen.chrStart.size()-1 << " \""<logMain << mapGen.pGe.gFastaFiles.at(ii)<<" : chr # " << mapGen.chrStart.size()-1 \ + << " \""<< mapGen.chrName.back() <<"\"" \ + << " chrStart: "<logMain << "Chromosome sequence lengths: \n"; for (uint ii=0;iilogMain << mapGen.chrName[ii] <<"\t"<< mapGen.chrLength[ii] << "\n"; }; }; diff --git a/source/loadGTF.cpp b/source/loadGTF.cpp deleted file mode 100644 index 8cc5d9a7..00000000 --- a/source/loadGTF.cpp +++ /dev/null @@ -1,333 +0,0 @@ -#include "loadGTF.h" - -#include "IncludeDefine.h" -#include "ErrorWarning.h" -#include "serviceFuns.cpp" -#include "streamFuns.h" -#include "TimeFunctions.h" - -#include -#include - - -#define GTF_exonLoci_size 4 -#define GTF_exonTrID(ii) ((ii)*GTF_exonLoci_size) -#define GTF_exonStart(ii) ((ii)*GTF_exonLoci_size+1) -#define GTF_exonEnd(ii) ((ii)*GTF_exonLoci_size+2) -#define GTF_exonGeID(ii) ((ii)*GTF_exonLoci_size+3) - -#define GTF_extrLoci_size 6 -#define GTF_extrTrStart(ii) ((ii)*GTF_extrLoci_size) -#define GTF_extrTrEnd(ii) ((ii)*GTF_extrLoci_size+1) -#define GTF_extrTrID(ii) ((ii)*GTF_extrLoci_size+2) -#define GTF_extrExStart(ii) ((ii)*GTF_extrLoci_size+3) -#define GTF_extrExEnd(ii) ((ii)*GTF_extrLoci_size+4) -#define GTF_extrGeID(ii) ((ii)*GTF_extrLoci_size+5) - -#define GTF_exgeLoci_size 5 -#define GTF_exgeExStart(ii) ((ii)*GTF_exgeLoci_size+0) -#define GTF_exgeExEnd(ii) ((ii)*GTF_exgeLoci_size+1) -#define GTF_exgeExStrand(ii) ((ii)*GTF_exgeLoci_size+2) -#define GTF_exgeGeID(ii) ((ii)*GTF_exgeLoci_size+3) -#define GTF_exgeTrID(ii) ((ii)*GTF_exgeLoci_size+4) - - - -uint64 loadGTF(SjdbClass &sjdbLoci, Parameters &P, string dirOut, Genome &mapGen) {//load gtf file, add junctions to P.sjdb - //returns number of added junctions - if (mapGen.sjdbOverhang==0 || mapGen.pGe.sjdbGTFfile=="-") //no GTF - return 0; - - time_t rawTime; - time(&rawTime); - P.inOut->logMain << timeMonthDayTime(rawTime) <<" ..... processing annotations GTF\n" <logStdOut << timeMonthDayTime(rawTime) <<" ..... processing annotations GTF\n" <> geneAttr; - - ifstream sjdbStreamIn ( mapGen.pGe.sjdbGTFfile.c_str() ); - if (sjdbStreamIn.fail()) { - ostringstream errOut; - errOut << "FATAL error, could not open file pGe.sjdbGTFfile=" << mapGen.pGe.sjdbGTFfile <<"\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); - }; - - if (mapGen.chrNameIndex.size()==0) - { - for (uint64 ii=0;ii transcriptIDnumber, geneIDnumber; - - uint64 exonN=0; - while (sjdbStreamIn.good()) {//count the number of exons - string chr1,ddd2,featureType; - sjdbStreamIn >> chr1 >> ddd2 >> featureType; - if (chr1.substr(0,1)!="#" && featureType==mapGen.pGe.sjdbGTFfeatureExon) { - exonN++; - }; - sjdbStreamIn.ignore(1000000000,'\n'); //ignore the rest of the line - }; - - if (exonN==0) { - ostringstream errOut; - errOut << "Fatal INPUT FILE error, no ""exon"" lines in the GTF file: " << mapGen.pGe.sjdbGTFfile <<"\n"; - errOut << "Solution: check the formatting of the GTF file, it must contain some lines with ""exon"" in the 3rd column.\n"; - errOut << " Make sure the GTF file is unzipped.\n"; - errOut << " If exons are marked with a different word, use --sjdbGTFfeatureExon .\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); - }; - - uint64* exonLoci=new uint64 [exonN*GTF_exonLoci_size]; - char* transcriptStrand = new char [exonN]; - vector transcriptID, geneID; - - exonN=0;//re-calculate - sjdbStreamIn.clear(); - sjdbStreamIn.seekg(0,ios::beg); - while (sjdbStreamIn.good()) { - - string oneLine,chr1,ddd2,featureType; - getline(sjdbStreamIn,oneLine); - istringstream oneLineStream (oneLine); - - oneLineStream >> chr1 >> ddd2 >> featureType; - if (chr1.substr(0,1)!="#" && featureType==mapGen.pGe.sjdbGTFfeatureExon) {//exonic line, process - - if (mapGen.pGe.sjdbGTFchrPrefix!="-") chr1=mapGen.pGe.sjdbGTFchrPrefix + chr1; - - if (mapGen.chrNameIndex.count(chr1)==0) {//chr not in Genome - P.inOut->logMain << "WARNING: while processing pGe.sjdbGTFfile=" << mapGen.pGe.sjdbGTFfile <<": chromosome '"<logMain << oneLine <<"\n"<> ex1 >> ex2 >> ddd2 >> str1 >> ddd2; //read all fields except the last - - string oneLine1; - getline(oneLineStream, oneLine1);//get the last field - replace(oneLine1.begin(),oneLine1.end(),';',' ');//to separate attributes - replace(oneLine1.begin(),oneLine1.end(),'=',' ');//for GFF3 processing - replace(oneLine1.begin(),oneLine1.end(),'\t',' ');//replace tabs - replace(oneLine1.begin(),oneLine1.end(),'\"',' ');//now the only separator is space - - //string trID(""), gID(""), attr1(""),gName(""),gBiotype(""); - vector> exAttrNames({ {mapGen.pGe.sjdbGTFtagExonParentTranscript}, {mapGen.pGe.sjdbGTFtagExonParentGene}, mapGen.pGe.sjdbGTFtagExonParentGeneName, mapGen.pGe.sjdbGTFtagExonParentGeneType }); //trID, gID, gName, gBiotype - vector exAttr; //trID, gID, gName, gBiotype - exAttr.resize(exAttrNames.size()); - - for (uint32 ii=0; iilogMain << "WARNING: while processing pGe.sjdbGTFfile=" << mapGen.pGe.sjdbGTFfile <<": no transcript_id for line:\n"; - P.inOut->logMain << oneLine <<"\n"<logMain << "WARNING: while processing pGe.sjdbGTFfile=" << mapGen.pGe.sjdbGTFfile <<": no gene_id for line:\n"; - P.inOut->logMain << oneLine <<"\n"< (exAttr[0],(uint64) transcriptIDnumber.size()));//insert new element if necessary with a new numeric value - if (transcriptID.size() < transcriptIDnumber.size()) transcriptID.push_back(exAttr[0]); - if (str1=='+') { - transcriptStrand[transcriptIDnumber[exAttr[0]]]=1; - } else if (str1=='-') { - transcriptStrand[transcriptIDnumber[exAttr[0]]]=2; - } else { - transcriptStrand[transcriptIDnumber[exAttr[0]]]=0; - }; - - geneIDnumber.insert(std::pair (exAttr[1],(uint64) geneIDnumber.size()));//insert new element if necessary with a $ - if (geneID.size() < geneIDnumber.size()) {//new gene is added - geneID.push_back(exAttr[1]); - geneAttr.push_back({exAttr[2],exAttr[3]}); - }; - - exonLoci[GTF_exonTrID(exonN)]=transcriptIDnumber[exAttr[0]]; - exonLoci[GTF_exonStart(exonN)]=ex1+mapGen.chrStart[mapGen.chrNameIndex[chr1]]-1; - exonLoci[GTF_exonEnd(exonN)]=ex2+mapGen.chrStart[mapGen.chrNameIndex[chr1]]-1; - exonLoci[GTF_exonGeID(exonN)]=geneIDnumber[exAttr[1]]; - ++exonN; - };//if (chr1.substr(0,1)!="#" && featureType=="exon") - };// - - if (exonN==0) { - ostringstream errOut; - errOut << "Fatal INPUT FILE error, no valid ""exon"" lines in the GTF file: " << mapGen.pGe.sjdbGTFfile <<"\n"; - errOut << "Solution: check the formatting of the GTF file. Most likely cause is the difference in chromosome naming between GTF and FASTA file.\n"; - exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); - }; - //sort exonLoci by transcript ID and exon coordinates - qsort((void*) exonLoci, exonN, sizeof(uint64)*GTF_exonLoci_size, funCompareUint2); - - {//exon-gene data structures: exon start/end/strand/gene/transcript - //re-sort exons by exons loci - uint64* exgeLoci=new uint64 [exonN*GTF_exgeLoci_size]; //this also contains transcripts start and end - - for (uint64 iex=0; iex); - - ofstream & exgeOut = ofstrOpen(dirOut+"/exonGeTrInfo.tab",ERROR_OUT,P); - exgeOut<); - - ofstream trOut ((dirOut+"/transcriptInfo.tab").c_str()); - trOut<> mapGen.pGe.gChrBinNbits]; - if ( exonLoci[GTF_exonStart(exI)]<=exonLoci[GTF_exonEnd(exI-1)]+1 ) { - P.inOut->logMain << "WARNING: while processing pGe.sjdbGTFfile=" << mapGen.pGe.sjdbGTFfile <<": overlapping or touching exons:\n"; - P.inOut->logMain << mapGen.chrName[chr1] <<"\t"<< exonLoci[GTF_exonStart(exI-1)]+1-mapGen.chrStart[chr1] << "\t"<< exonLoci[GTF_exonEnd(exI-1)]+1-mapGen.chrStart[chr1] <<"\n"; - P.inOut->logMain << mapGen.chrName[chr1] <<"\t"<< exonLoci[GTF_exonStart(exI)]+1-mapGen.chrStart[chr1] << "\t"<< exonLoci[GTF_exonEnd(exI)]+1-mapGen.chrStart[chr1] <<"\n"; - } else { - sjLoci[sjN*sjStride]=exonLoci[GTF_exonEnd(exI-1)]+1; - sjLoci[sjN*sjStride+1]=exonLoci[GTF_exonStart(exI)]-1; - sjLoci[sjN*sjStride+2]=(uint64) transcriptStrand[trIDn]; - sjLoci[sjN*sjStride+3]=exonLoci[GTF_exonGeID(exI)]+1;//genes are numbered from 1 - sjN++; - }; - } else { - trIDn=exonLoci[GTF_exonTrID(exI)]; - }; - }; - - qsort((void*) sjLoci, sjN, sizeof(uint64)*sjStride, funCompareUint2); - - char strandChar[3]={'.','+','-'}; - uint64 sjdbN1=sjdbLoci.chr.size(); - sjdbLoci.gene.resize(sjdbN1); //need to resize in case sjdbLoci was loaded from files without gene attribute. TODO make sure gene is always present - for (uint64 ii=0;ii> mapGen.pGe.gChrBinNbits]; - sjdbLoci.chr.push_back(mapGen.chrName[chr1]); - sjdbLoci.start.push_back(sjLoci[ii*sjStride]+1-mapGen.chrStart[chr1]); - sjdbLoci.end.push_back(sjLoci[ii*sjStride+1]+1-mapGen.chrStart[chr1]); - sjdbLoci.str.push_back(strandChar[sjLoci[ii*sjStride+2]]); - sjdbLoci.gene.push_back({sjLoci[ii*sjStride+3]}); - } else { - sjdbLoci.gene.back().insert(sjLoci[ii*sjStride+3]); - }; - }; - - ofstream sjdbList ((dirOut+"/sjdbList.fromGTF.out.tab").c_str()); - for (uint64 ii=sjdbN1;iilogMain << "Processing pGe.sjdbGTFfile=" << mapGen.pGe.sjdbGTFfile <<", found:\n"; - P.inOut->logMain << "\t\t" << transcriptIDnumber.size() <<" transcripts\n" << "\t\t" << exonN << " exons (non-collapsed)\n" << "\t\t" << sjdbLoci.chr.size()-sjdbN1 << " collapsed junctions\n"; - time(&rawTime); - P.inOut->logMain << timeMonthDayTime(rawTime) <<" ..... finished GTF processing\n" < +#include +#include +#include +#include +#include + +extern "C" { +#define SIMDE_ENABLE_NATIVE_ALIASES +#include // AVX2 and lower +} + +#include "opal.h" + + +// I define aliases for SSE intrinsics, so they can be used in code not depending on SSE generation. +// If available, AVX2 is used because it has two times bigger register, thus everything is two times faster. +// #ifdef __AVX2__ +#if 1 //A.D.: now SIMDe will be taking care of the SIMD + +const int SIMD_REG_SIZE = 256; //!< number of bits in register +typedef __m256i __mxxxi; //!< represents register containing integers +#define _mmxxx_load_si _mm256_load_si256 +#define _mmxxx_store_si _mm256_store_si256 +#define _mmxxx_and_si _mm256_and_si256 +#define _mmxxx_testz_si _mm256_testz_si256 + +#define _mmxxx_adds_epi8 _mm256_adds_epi8 +#define _mmxxx_subs_epi8 _mm256_subs_epi8 +#define _mmxxx_min_epu8 _mm256_min_epu8 +#define _mmxxx_min_epi8 _mm256_min_epi8 +#define _mmxxx_max_epu8 _mm256_max_epu8 +#define _mmxxx_max_epi8 _mm256_max_epi8 +#define _mmxxx_set1_epi8 _mm256_set1_epi8 +#define _mmxxx_cmpgt_epi8 _mm256_cmpgt_epi8 + +#define _mmxxx_adds_epi16 _mm256_adds_epi16 +#define _mmxxx_subs_epi16 _mm256_subs_epi16 +#define _mmxxx_min_epi16 _mm256_min_epi16 +#define _mmxxx_max_epi16 _mm256_max_epi16 +#define _mmxxx_set1_epi16 _mm256_set1_epi16 +#define _mmxxx_cmpgt_epi16 _mm256_cmpgt_epi16 + +#define _mmxxx_add_epi32 _mm256_add_epi32 +#define _mmxxx_sub_epi32 _mm256_sub_epi32 +#define _mmxxx_min_epi32 _mm256_min_epi32 +#define _mmxxx_max_epi32 _mm256_max_epi32 +#define _mmxxx_set1_epi32 _mm256_set1_epi32 +#define _mmxxx_cmpgt_epi32 _mm256_cmpgt_epi32 + +#else // SSE4.1 + +const int SIMD_REG_SIZE = 128; +typedef __m128i __mxxxi; +#define _mmxxx_load_si _mm_load_si128 +#define _mmxxx_store_si _mm_store_si128 +#define _mmxxx_and_si _mm_and_si128 +#define _mmxxx_testz_si _mm_testz_si128 + +#define _mmxxx_adds_epi8 _mm_adds_epi8 +#define _mmxxx_subs_epi8 _mm_subs_epi8 +#define _mmxxx_min_epu8 _mm_min_epu8 +#define _mmxxx_min_epi8 _mm_min_epi8 +#define _mmxxx_max_epu8 _mm_max_epu8 +#define _mmxxx_max_epi8 _mm_max_epi8 +#define _mmxxx_set1_epi8 _mm_set1_epi8 +#define _mmxxx_cmpgt_epi8 _mm_cmpgt_epi8 + +#define _mmxxx_adds_epi16 _mm_adds_epi16 +#define _mmxxx_subs_epi16 _mm_subs_epi16 +#define _mmxxx_min_epi16 _mm_min_epi16 +#define _mmxxx_max_epi16 _mm_max_epi16 +#define _mmxxx_set1_epi16 _mm_set1_epi16 +#define _mmxxx_cmpgt_epi16 _mm_cmpgt_epi16 + +#define _mmxxx_add_epi32 _mm_add_epi32 +#define _mmxxx_sub_epi32 _mm_sub_epi32 +#define _mmxxx_min_epi32 _mm_min_epi32 +#define _mmxxx_max_epi32 _mm_max_epi32 +#define _mmxxx_set1_epi32 _mm_set1_epi32 +#define _mmxxx_cmpgt_epi32 _mm_cmpgt_epi32 + +#endif + + +//------------------------------------ SIMD PARAMETERS ---------------------------------// +static inline int simdIsAllZeroes(const __mxxxi& a) { + return _mmxxx_testz_si(a, a); +} + +/** + * Contains parameters and SIMD instructions specific for certain score type. + */ + +template struct SimdSW {}; + +template<> +struct SimdSW { + typedef char type; //!< Type that will be used for score + static const int numSeqs = SIMD_REG_SIZE / (8 * sizeof(char)); //!< Number of sequences that can be done in parallel. + static const bool satArthm = true; //!< True if saturation arithmetic is used, false otherwise. + static const bool negRange = true; //!< True if it uses negative range for score representation, goes with saturation + static inline __mxxxi add(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_adds_epi8(a, b); } + static inline __mxxxi sub(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_subs_epi8(a, b); } + static inline __mxxxi min(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_min_epu8(a, b); } + static inline __mxxxi max(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_max_epu8(a, b); } + static inline __mxxxi cmpgt(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_cmpgt_epi8(a, b); } + static inline __mxxxi set1(int a) { return _mmxxx_set1_epi8(a); } +}; + +template<> +struct SimdSW { + typedef short type; + static const int numSeqs = SIMD_REG_SIZE / (8 * sizeof(short)); + static const bool satArthm = true; + static const bool negRange = false; + static inline __mxxxi add(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_adds_epi16(a, b); } + static inline __mxxxi sub(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_subs_epi16(a, b); } + static inline __mxxxi min(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_min_epi16(a, b); } + static inline __mxxxi max(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_max_epi16(a, b); } + static inline __mxxxi cmpgt(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_cmpgt_epi16(a, b); } + static inline __mxxxi set1(int a) { return _mmxxx_set1_epi16(a); } +}; + +template<> +struct SimdSW { + typedef int type; + static const int numSeqs = SIMD_REG_SIZE / (8 * sizeof(int)); + static const bool satArthm = false; + static const bool negRange = false; + static inline __mxxxi add(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_add_epi32(a, b); } + static inline __mxxxi sub(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_sub_epi32(a, b); } + static inline __mxxxi min(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_min_epi32(a, b); } + static inline __mxxxi max(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_max_epi32(a, b); } + static inline __mxxxi cmpgt(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_cmpgt_epi32(a, b); } + static inline __mxxxi set1(int a) { return _mmxxx_set1_epi32(a); } +}; +//--------------------------------------------------------------------------------------// + + +static bool loadNextSequence(int &nextDbSeqIdx, int dbLength, int &currDbSeqIdx, unsigned char * &currDbSeqPos, + int &currDbSeqLength, unsigned char ** db, int dbSeqLengths[], bool calculated[], + int &numEndedDbSeqs); + + +// For debugging +template +void print_mmxxxi(__mxxxi mm) { + typename SIMD::type unpacked[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpacked, mm); + for (int i = 0; i < SIMD::numSeqs; i++) + printf("%d ", unpacked[i]); +} + +// This structure represents cell in dynamic programming matrix, but only with E and H values. +struct CellEH { + __mxxxi H; + __mxxxi E; +}; + +/** + * @param stopOnOverflow If true, function will stop when first overflow happens. + * If false, function will not stop but continue with next sequence. + * + */ +template +static int searchDatabaseSW_(unsigned char query[], int queryLength, + unsigned char** db, int dbLength, int dbSeqLengths[], + int gapOpen, int gapExt, int* scoreMatrix, int alphabetLength, + OpalSearchResult* results[], const int searchType, bool calculated[], + int overflowMethod) { + + const typename SIMD::type LOWER_BOUND = std::numeric_limits::min(); + const typename SIMD::type UPPER_BOUND = std::numeric_limits::max(); + + bool overflowOccured = false; // True if overflow was detected at least once. + + // ----------------------- CHECK ARGUMENTS -------------------------- // + // Check if Q, R or scoreMatrix have values too big for used score type + if (gapOpen < LOWER_BOUND || UPPER_BOUND < gapOpen || gapExt < LOWER_BOUND || UPPER_BOUND < gapExt) { + return 1; + } + if (!SIMD::satArthm) { + // These extra limits are enforced so overflow could be detected more efficiently + if (gapOpen <= LOWER_BOUND/2 || UPPER_BOUND/2 <= gapOpen || gapExt <= LOWER_BOUND/2 || UPPER_BOUND/2 <= gapExt) { + return OPAL_ERR_OVERFLOW; + } + } + + for (int r = 0; r < alphabetLength; r++) + for (int c = 0; c < alphabetLength; c++) { + int score = scoreMatrix[r * alphabetLength + c]; + if (score < LOWER_BOUND || UPPER_BOUND < score) { + return OPAL_ERR_OVERFLOW; + } + if (!SIMD::satArthm) { + if (score <= LOWER_BOUND/2 || UPPER_BOUND/2 <= score) + return OPAL_ERR_OVERFLOW; + } + } + // ------------------------------------------------------------------ // + + + // ------------------------ INITIALIZATION -------------------------- // + __mxxxi zeroes = SIMD::set1(0); + __mxxxi scoreZeroes; // 0 normally, but lower bound if using negative range + if (SIMD::negRange) { + scoreZeroes = SIMD::set1(LOWER_BOUND); + } else { + scoreZeroes = zeroes; + } + + int numEndedDbSeqs = 0; // Number of sequences that ended + int nextDbSeqIdx = 0; // Index in db of next sequence that we will try to load. + // Index in db. -1 for null sequence (null sequence == no sequence). + int currDbSeqsIdxs[SIMD::numSeqs]; + // Pointer to current element for each current database sequence. 0 for null sequence. + unsigned char* currDbSeqsPos[SIMD::numSeqs]; + // Lengths of remaining parts of sequences. -1 for null sequence. + int currDbSeqsLengths[SIMD::numSeqs]; + + // Needed in order to find the most early result, which is a nice condition to have. + int currDbSeqsBestScore[SIMD::numSeqs]; + // Row index of best score for each current database sequence. + int currDbSeqsBestScoreRow[SIMD::numSeqs]; + // Column index of best score for each current database sequence. + int currDbSeqsBestScoreColumn[SIMD::numSeqs]; + + // Profile query -> here we store preprocessed score data needed in core loop. + // It is recalculated for each column. + __mxxxi P[alphabetLength]; + + // Load initial sequences + for (int i = 0; i < SIMD::numSeqs; i++) { + currDbSeqsBestScore[i] = LOWER_BOUND; + loadNextSequence(nextDbSeqIdx, dbLength, currDbSeqsIdxs[i], currDbSeqsPos[i], + currDbSeqsLengths[i], db, dbSeqLengths, calculated, numEndedDbSeqs); + } + + // Q is gap open penalty, R is gap ext penalty. + __mxxxi Q = SIMD::set1(gapOpen); + __mxxxi R = SIMD::set1(gapExt); + + int rowsWithImprovement[queryLength]; // Indexes of rows where one of sequences improved score. + + // Previous Hs, previous Es, previous F, all signed short. + CellEH prevColumn[queryLength]; // Stores results of previous column in matrix. + // Initialize all values to 0 + for (int i = 0; i < queryLength; i++) { + prevColumn[i].H = prevColumn[i].E = scoreZeroes; + } + + __mxxxi maxH = scoreZeroes; // Best score in sequence + // ------------------------------------------------------------------ // + + + // For each column + while (numEndedDbSeqs < dbLength) { + // -------------------- CALCULATE QUERY PROFILE ------------------------- // + // TODO: Rognes uses pshufb here, I don't know how/why? + typename SIMD::type profileRow[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + for (unsigned char letter = 0; letter < alphabetLength; letter++) { + int* scoreMatrixRow = scoreMatrix + letter*alphabetLength; + for (int i = 0; i < SIMD::numSeqs; i++) { + unsigned char* dbSeqPos = currDbSeqsPos[i]; + if (dbSeqPos != 0) + profileRow[i] = (typename SIMD::type)scoreMatrixRow[*dbSeqPos]; + } + P[letter] = _mmxxx_load_si((__mxxxi const*)profileRow); + } + // ---------------------------------------------------------------------- // + + // Previous cells: u - up, l - left, ul - up left + __mxxxi uF, uH, ulH; + uF = uH = ulH = scoreZeroes; // F[-1, c] = H[-1, c] = H[-1, c-1] = 0 + + __mxxxi ofTest = scoreZeroes; // Used for detecting the overflow when not using saturated ar + + int rowsWithImprovementLength = 0; + + // ----------------------- CORE LOOP (ONE COLUMN) ----------------------- // + for (int r = 0; r < queryLength; r++) { // For each cell in column + // Calculate E = max(lH-Q, lE-R) + __mxxxi E = SIMD::max(SIMD::sub(prevColumn[r].H, Q), SIMD::sub(prevColumn[r].E, R)); + + // Calculate F = max(uH-Q, uF-R) + __mxxxi F = SIMD::max(SIMD::sub(uH, Q), SIMD::sub(uF, R)); + + // Calculate H + __mxxxi H = SIMD::max(F, E); + if (!SIMD::negRange) { + // If not using negative range, then H could be negative at this moment so we need this + H = SIMD::max(H, zeroes); + } + __mxxxi ulH_P = SIMD::add(ulH, P[query[r]]); + // If using negative range: if ulH_P >= 0 then we have overflow + + H = SIMD::max(H, ulH_P); + // If using negative range: H will always be negative, even if ulH_P overflowed + + // Save data needed for overflow detection. Not more then one condition will fire + if (SIMD::negRange) + ofTest = _mmxxx_and_si(ofTest, ulH_P); + if (!SIMD::satArthm) + ofTest = SIMD::min(ofTest, ulH_P); + + // If we need end location, remember row with best score. + if (searchType != OPAL_SEARCH_SCORE) { + // We remember rows that had max scores, in order to find out the row of best score. + rowsWithImprovement[rowsWithImprovementLength] = r; + // TODO(martin): simdIsAllZeroes seems to bring significant slowdown, but I could + // not find way to avoid it. + rowsWithImprovementLength += 1 - simdIsAllZeroes(SIMD::cmpgt(H, maxH)); + } + + maxH = SIMD::max(maxH, H); // update best score + + // Set uF, uH, ulH + uF = F; + uH = H; + ulH = prevColumn[r].H; + + // Remeber values so they can be used in next column. + prevColumn[r].E = E; + prevColumn[r].H = H; + + // For saturated: score is biased everywhere, but just score: E, F, H + // Also, all scores except ulH_P certainly have value < 0 + } + // ---------------------------------------------------------------------- // + + for (int seqIdx = 0; seqIdx < SIMD::numSeqs; seqIdx++) { + currDbSeqsLengths[seqIdx] -= currDbSeqsLengths[seqIdx] > 0; + } + + typename SIMD::type unpackedMaxH[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedMaxH, maxH); + + // ------------------------ OVERFLOW DETECTION -------------------------- // + bool overflowed[SIMD::numSeqs]; + if (!SIMD::satArthm) { + // This check is based on following assumptions: + // - overflow wraps + // - Q, R and all scores from scoreMatrix are between LOWER_BOUND/2 and UPPER_BOUND/2 exclusive + typename SIMD::type unpackedOfTest[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedOfTest, ofTest); + for (int i = 0; i < SIMD::numSeqs; i++) { + overflowed[i] = currDbSeqsPos[i] != 0 && unpackedOfTest[i] <= LOWER_BOUND / 2; + if (overflowMethod == OPAL_OVERFLOW_BUCKETS && overflowed[i]) { + // In buckets method, we stop calculation when overflow is detected. + return OPAL_ERR_OVERFLOW; + } + } + } else { + if (SIMD::negRange) { + // Since I use saturation, I check if minUlH_P was non negative + typename SIMD::type unpackedOfTest[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedOfTest, ofTest); + for (int i = 0; i < SIMD::numSeqs; i++) { + overflowed[i] = currDbSeqsPos[i] != 0 && unpackedOfTest[i] >= 0; + if (overflowMethod == OPAL_OVERFLOW_BUCKETS && overflowed[i]) { + return OPAL_ERR_OVERFLOW; + } + } + } else { + // I check if upper bound is reached + for (int i = 0; i < SIMD::numSeqs; i++) { + overflowed[i] = currDbSeqsPos[i] != 0 && unpackedMaxH[i] == UPPER_BOUND; + if (overflowMethod == OPAL_OVERFLOW_BUCKETS && overflowed[i]) { + return OPAL_ERR_OVERFLOW; + } + } + } + } + // ---------------------------------------------------------------------- // + + bool overflowDetected = false; // True if overflow was detected in last column. + bool sequenceEnded = false; // True if a sequence ended in last column. + for (int seqIdx = 0; seqIdx < SIMD::numSeqs; seqIdx++) { + overflowDetected = overflowDetected || overflowed[seqIdx]; + sequenceEnded = sequenceEnded || (currDbSeqsLengths[seqIdx] == 0); + } + overflowOccured = overflowOccured || overflowDetected; + + + // --------- Update end location of alignment ----------- // + if (searchType != OPAL_SEARCH_SCORE) { + for (int i = 0; i < rowsWithImprovementLength; i++) { + int r = rowsWithImprovement[i]; + typename SIMD::type unpackedH[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedH, prevColumn[r].H); + for (int j = 0; j < SIMD::numSeqs; j++) { + if (currDbSeqsPos[j] != 0 && !overflowed[j]) { // If not null sequence or overflowedresult->endLocationQuery = + if (unpackedH[j] > currDbSeqsBestScore[j]) { + currDbSeqsBestScore[j] = unpackedH[j]; + currDbSeqsBestScoreRow[j] = r; + currDbSeqsBestScoreColumn[j] = dbSeqLengths[currDbSeqsIdxs[j]] + - currDbSeqsLengths[j] - 1; + } + } + } + } + } + // ------------------------------------------------------ // + + + // --------------------- CHECK AND HANDLE SEQUENCE END ------------------ // + if (overflowDetected || sequenceEnded) { // If at least one sequence ended + typename SIMD::type resetMask[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + + for (int i = 0; i < SIMD::numSeqs; i++) { + if (currDbSeqsPos[i] != 0) { // If not null sequence + if (overflowed[i] || currDbSeqsLengths[i] == 0) { // If sequence ended + numEndedDbSeqs++; + if (!overflowed[i]) { + // Save score and mark as calculated + calculated[currDbSeqsIdxs[i]] = true; + opalSearchResultSetScore(results[currDbSeqsIdxs[i]], unpackedMaxH[i]); + if (SIMD::negRange) { + results[currDbSeqsIdxs[i]]->score -= LOWER_BOUND; + } + if (searchType != OPAL_SEARCH_SCORE) { + results[currDbSeqsIdxs[i]]->endLocationQuery = currDbSeqsBestScoreRow[i]; + results[currDbSeqsIdxs[i]]->endLocationTarget = currDbSeqsBestScoreColumn[i]; + } else { + results[currDbSeqsIdxs[i]]->endLocationQuery = -1; + results[currDbSeqsIdxs[i]]->endLocationTarget = -1; + } + } + currDbSeqsBestScore[i] = LOWER_BOUND; + // Load next sequence + loadNextSequence(nextDbSeqIdx, dbLength, currDbSeqsIdxs[i], currDbSeqsPos[i], + currDbSeqsLengths[i], db, dbSeqLengths, calculated, numEndedDbSeqs); + // If negative range, sets to LOWER_BOUND when used with saturated add and value < 0, + // otherwise sets to zero when used with and. + resetMask[i] = SIMD::negRange ? LOWER_BOUND : 0; + } else { + // Does not change anything when used with saturated add / and. + resetMask[i] = SIMD::negRange ? 0 : -1; + if (currDbSeqsPos[i] != 0) + currDbSeqsPos[i]++; // If not new and not null, move for one element + } + } + } + // Reset previous columns (Es and Hs) and maxH + __mxxxi resetMaskPacked = _mmxxx_load_si((__mxxxi const*)resetMask); + if (SIMD::negRange) { + for (int i = 0; i < queryLength; i++) { + prevColumn[i].H = SIMD::add(prevColumn[i].H, resetMaskPacked); + prevColumn[i].E = SIMD::add(prevColumn[i].E, resetMaskPacked); + } + maxH = SIMD::add(maxH, resetMaskPacked); + } else { + for (int i = 0; i < queryLength; i++) { + prevColumn[i].H = _mmxxx_and_si(prevColumn[i].H, resetMaskPacked); + prevColumn[i].E = _mmxxx_and_si(prevColumn[i].E, resetMaskPacked); + } + maxH = _mmxxx_and_si(maxH, resetMaskPacked); + } + } else { // If no sequences ended + // Move for one element in all sequences + for (int i = 0; i < SIMD::numSeqs; i++) + currDbSeqsPos[i] += (currDbSeqsPos[i] != 0); + } + // ---------------------------------------------------------------------- // + } + + if (overflowOccured) { + return OPAL_ERR_OVERFLOW; + } + return 0; +} + +static inline bool loadNextSequence(int &nextDbSeqIdx, int dbLength, int &currDbSeqIdx, unsigned char* &currDbSeqPos, + int &currDbSeqLength, unsigned char** db, int dbSeqLengths[], bool calculated[], + int &numEndedDbSeqs) { + while (nextDbSeqIdx < dbLength && calculated[nextDbSeqIdx]) { + nextDbSeqIdx++; + numEndedDbSeqs++; + } + if (nextDbSeqIdx < dbLength) { // If there is sequence to load + currDbSeqIdx = nextDbSeqIdx; + currDbSeqPos = db[nextDbSeqIdx]; + currDbSeqLength = dbSeqLengths[nextDbSeqIdx]; + nextDbSeqIdx++; + return true; + } else { // If there are no more sequences to load, load "null" sequence + currDbSeqIdx = currDbSeqLength = -1; // Set to -1 if there are no more sequences + currDbSeqPos = 0; + return false; + } +} + +/** + * @param If skip[i] is true, result for sequence #i will not be calculated. + * If skip is NULL, all results will be calculated. + */ +static int searchDatabaseSW(unsigned char query[], int queryLength, + unsigned char** db, int dbLength, int dbSeqLengths[], + int gapOpen, int gapExt, int* scoreMatrix, int alphabetLength, + OpalSearchResult* results[], const int searchType, bool skip[], int overflowMethod) { + int resultCode = 0; + // Do buckets only if using buckets overflow method. + const int chunkSize = overflowMethod == OPAL_OVERFLOW_BUCKETS ? 1024 : dbLength; + bool* calculated = new bool[chunkSize]; + for (int startIdx = 0; startIdx < dbLength; startIdx += chunkSize) { + unsigned char** db_ = db + startIdx; + int* dbSeqLengths_ = dbSeqLengths + startIdx; + OpalSearchResult** results_ = results + startIdx; + int dbLength_ = startIdx + chunkSize >= dbLength ? dbLength - startIdx : chunkSize; + for (int i = 0; i < dbLength_; i++) { + calculated[i] = skip ? skip[i] : false; + } + resultCode = searchDatabaseSW_< SimdSW >( + query, queryLength, db_, dbLength_, dbSeqLengths_, + gapOpen, gapExt, scoreMatrix, alphabetLength, results_, + searchType, calculated, overflowMethod); + if (resultCode == OPAL_ERR_OVERFLOW) { + resultCode = searchDatabaseSW_< SimdSW >( + query, queryLength, db_, dbLength_, dbSeqLengths_, + gapOpen, gapExt, scoreMatrix, alphabetLength, results_, + searchType, calculated, overflowMethod); + if (resultCode == OPAL_ERR_OVERFLOW) { + resultCode = searchDatabaseSW_< SimdSW >( + query, queryLength, + db_, dbLength_, dbSeqLengths_, + gapOpen, gapExt, scoreMatrix, alphabetLength, results_, + searchType, calculated, overflowMethod); + if (resultCode != 0) + break; + } + } + } + + delete[] calculated; + return resultCode; +} + + + + + + + + + +//------------------------------------ SIMD PARAMETERS ---------------------------------// +/** + * Contains parameters and SIMD instructions specific for certain score type. + */ +template class Simd {}; + +template<> +struct Simd { + typedef char type; //!< Type that will be used for score + static const int numSeqs = SIMD_REG_SIZE / (8 * sizeof(char)); //!< Number of sequences that can be done in parallel. + static const bool satArthm = true; //!< True if saturation arithmetic is used, false otherwise. + static inline __mxxxi add(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_adds_epi8(a, b); } + static inline __mxxxi sub(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_subs_epi8(a, b); } + static inline __mxxxi min(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_min_epi8(a, b); } + static inline __mxxxi max(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_max_epi8(a, b); } + static inline __mxxxi cmpgt(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_cmpgt_epi8(a, b); } + static inline __mxxxi set1(int a) { return _mmxxx_set1_epi8(a); } +}; + +template<> +struct Simd { + typedef short type; + static const int numSeqs = SIMD_REG_SIZE / (8 * sizeof(short)); + static const bool satArthm = true; + static inline __mxxxi add(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_adds_epi16(a, b); } + static inline __mxxxi sub(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_subs_epi16(a, b); } + static inline __mxxxi min(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_min_epi16(a, b); } + static inline __mxxxi max(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_max_epi16(a, b); } + static inline __mxxxi cmpgt(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_cmpgt_epi16(a, b); } + static inline __mxxxi set1(int a) { return _mmxxx_set1_epi16(a); } +}; + +template<> +struct Simd { + typedef int type; + static const int numSeqs = SIMD_REG_SIZE / (8 * sizeof(int)); + static const bool satArthm = false; + static inline __mxxxi add(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_add_epi32(a, b); } + static inline __mxxxi sub(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_sub_epi32(a, b); } + static inline __mxxxi min(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_min_epi32(a, b); } + static inline __mxxxi max(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_max_epi32(a, b); } + static inline __mxxxi cmpgt(const __mxxxi& a, const __mxxxi& b) { return _mmxxx_cmpgt_epi32(a, b); } + static inline __mxxxi set1(int a) { return _mmxxx_set1_epi32(a); } +}; +//--------------------------------------------------------------------------------------// + + + + +template +static int searchDatabase_(unsigned char query[], int queryLength, + unsigned char** db, int dbLength, int dbSeqLengths[], + int gapOpen, int gapExt, int* scoreMatrix, int alphabetLength, + OpalSearchResult* results[], const int searchType, bool calculated[], int overflowMethod) { + + static const typename SIMD::type LOWER_BOUND = std::numeric_limits::min(); + static const typename SIMD::type UPPER_BOUND = std::numeric_limits::max(); + // Used to represent -inf. Must be larger then lower bound to avoid overflow. + // TOOD(martin): Is it enough to use gapExt here? Should I use gapOpen instead? + static const typename SIMD::type LOWER_SCORE_BOUND = LOWER_BOUND + gapExt; + + bool overflowOccured = false; // True if oveflow was detected at least once. + + // ----------------------- CHECK ARGUMENTS -------------------------- // + // Check if Q, R or scoreMatrix have values too big for used score type + if (gapOpen < LOWER_BOUND || UPPER_BOUND < gapOpen || gapExt < LOWER_BOUND || UPPER_BOUND < gapExt) { + return 1; + } + if (!SIMD::satArthm) { + // These extra limits are enforced so overflow could be detected more efficiently + if (gapOpen <= LOWER_BOUND/2 || UPPER_BOUND/2 <= gapOpen || gapExt <= LOWER_BOUND/2 || UPPER_BOUND/2 <= gapExt) { + return 1; + } + } + + for (int r = 0; r < alphabetLength; r++) + for (int c = 0; c < alphabetLength; c++) { + int score = scoreMatrix[r * alphabetLength + c]; + if (score < LOWER_BOUND || UPPER_BOUND < score) { + return 1; + } + if (!SIMD::satArthm) { + if (score <= LOWER_BOUND/2 || UPPER_BOUND/2 <= score) + return 1; + } + } + + // TODO: If not saturated arithmetic check if inital values of H (-gapOpen - i * gapExt) cause overflow + // ------------------------------------------------------------------ // + + + // ------------------------ INITIALIZATION -------------------------- // + const __mxxxi ZERO_SIMD = SIMD::set1(0); + const __mxxxi LOWER_BOUND_SIMD = SIMD::set1(LOWER_BOUND); + const __mxxxi LOWER_SCORE_BOUND_SIMD = SIMD::set1(LOWER_SCORE_BOUND); + + int nextDbSeqIdx = 0; // index in db + int currDbSeqsIdxs[SIMD::numSeqs]; // index in db + unsigned char* currDbSeqsPos[SIMD::numSeqs]; // current element for each current database sequence + int currDbSeqsLengths[SIMD::numSeqs]; + bool justLoaded[SIMD::numSeqs] = {0}; // True if sequence was just loaded into channel + bool seqJustLoaded = false; // True if at least one sequence was just loaded into channel + int shortestDbSeqLength = -1; // length of shortest sequence among current database sequences + int numEndedDbSeqs = 0; // Number of sequences that ended + + // Row index of best score for each current database sequence. Used for HW and OV. + int currDbSeqsBestScoreColumn[SIMD::numSeqs]; + + // Load initial sequences + for (int i = 0; i < SIMD::numSeqs; i++) + if (loadNextSequence(nextDbSeqIdx, dbLength, currDbSeqsIdxs[i], currDbSeqsPos[i], + currDbSeqsLengths[i], db, dbSeqLengths, calculated, numEndedDbSeqs)) { + justLoaded[i] = seqJustLoaded = true; + // Update shortest sequence length if new sequence was loaded + if (shortestDbSeqLength == -1 || currDbSeqsLengths[i] < shortestDbSeqLength) + shortestDbSeqLength = currDbSeqsLengths[i]; + } + + // Q is gap open penalty, R is gap ext penalty. + const __mxxxi Q = SIMD::set1(gapOpen); + const __mxxxi R = SIMD::set1(gapExt); + + // Previous H column (array), previous E column (array), previous F, all signed short + __mxxxi prevHs[queryLength]; + __mxxxi prevEs[queryLength]; + // Initialize all values + for (int r = 0; r < queryLength; r++) { + if (MODE == OPAL_MODE_OV) + prevHs[r] = ZERO_SIMD; + else { // - Q - r * R + if (r == 0) + prevHs[0] = SIMD::sub(ZERO_SIMD, Q); + else + prevHs[r] = SIMD::sub(prevHs[r-1], R); + } + + prevEs[r] = LOWER_SCORE_BOUND_SIMD; + } + + // u - up, ul - up left + __mxxxi uH, ulH; + if (MODE == OPAL_MODE_NW) { + ulH = ZERO_SIMD; + uH = SIMD::sub(R, Q); // -Q + R + } + + __mxxxi maxLastRowH = LOWER_BOUND_SIMD; // Keeps track of maximum H in last row + // ------------------------------------------------------------------ // + + + int columnsSinceLastSeqEnd = 0; + // For each column + while (numEndedDbSeqs < dbLength) { + // -------------------- CALCULATE QUERY PROFILE ------------------------- // + // TODO: Rognes uses pshufb here, I don't know how/why? + __mxxxi P[alphabetLength]; + typename SIMD::type profileRow[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + for (unsigned char letter = 0; letter < alphabetLength; letter++) { + int* scoreMatrixRow = scoreMatrix + letter*alphabetLength; + for (int i = 0; i < SIMD::numSeqs; i++) { + unsigned char* dbSeqPos = currDbSeqsPos[i]; + if (dbSeqPos != 0) + profileRow[i] = (typename SIMD::type)scoreMatrixRow[*dbSeqPos]; + } + P[letter] = _mmxxx_load_si((__mxxxi const*)profileRow); + } + // ---------------------------------------------------------------------- // + + // u - up + __mxxxi uF = LOWER_SCORE_BOUND_SIMD; + + // Database sequence has fixed start and end only in NW + if (MODE == OPAL_MODE_NW) { + if (seqJustLoaded) { + typename SIMD::type resetMask[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + for (int i = 0; i < SIMD::numSeqs; i++) + resetMask[i] = justLoaded[i] ? 0 : -1; + const __mxxxi resetMaskPacked = _mmxxx_load_si((__mxxxi const*)resetMask); + ulH = _mmxxx_and_si(uH, resetMaskPacked); + } else { + ulH = uH; + } + + uH = SIMD::sub(uH, R); // uH is -Q - c*R + // NOTE: Setup of ulH and uH for first column is done when sequence is loaded. + } else { + uH = ulH = ZERO_SIMD; + } + + __mxxxi minE, minF; + minE = minF = SIMD::set1(UPPER_BOUND); + __mxxxi maxH = LOWER_BOUND_SIMD; // Max H in this column + __mxxxi H; + + __mxxxi firstRow_uH, firstRow_ulH; // Values of uH and ulH from first row of column + + if (MODE == OPAL_MODE_NW) { + firstRow_uH = uH; + firstRow_ulH = ulH; + } + + __mxxxi prevMaxLastRowH = maxLastRowH; + // ----------------------- CORE LOOP (ONE COLUMN) ----------------------- // + for (int r = 0; r < queryLength; r++) { // For each cell in column + // Calculate E = max(lH-Q, lE-R) + __mxxxi E = SIMD::max(SIMD::sub(prevHs[r], Q), SIMD::sub(prevEs[r], R)); // E could overflow + + // Calculate F = max(uH-Q, uF-R) + __mxxxi F = SIMD::max(SIMD::sub(uH, Q), SIMD::sub(uF, R)); // F could overflow + minF = SIMD::min(minF, F); // For overflow detection + + // Calculate H + H = SIMD::max(F, E); + __mxxxi ulH_P = SIMD::add(ulH, P[query[r]]); + H = SIMD::max(H, ulH_P); // H could overflow + + maxH = SIMD::max(maxH, H); // update best score in column + + // Set uF, uH, ulH + uF = F; + uH = H; + ulH = prevHs[r]; + + // Update prevHs, prevEs in advance for next column + prevEs[r] = E; + prevHs[r] = H; + } + // ---------------------------------------------------------------------- // + + maxLastRowH = SIMD::max(maxLastRowH, H); + + if (MODE == OPAL_MODE_NW) { + uH = firstRow_uH; + ulH = firstRow_ulH; + } + + // Find minE, which should be checked with minE == LOWER_BOUND for overflow + for (int r = 0; r < queryLength; r++) + minE = SIMD::min(minE, prevEs[r]); + + columnsSinceLastSeqEnd++; + + typename SIMD::type unpackedMaxH[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedMaxH, maxH); + + // ------------------------ OVERFLOW DETECTION -------------------------- // + bool overflowDetected = false; // True if overflow was detected for this column. + bool overflowed[SIMD::numSeqs]; + if (!SIMD::satArthm) { + /* // This check is based on following assumptions: + // - overflow wraps + // - Q, R and all scores from scoreMatrix are between LOWER_BOUND/2 and UPPER_BOUND/2 exclusive + typename SIMD::type* unpackedOfTest = (typename SIMD::type *)&ofTest; + for (int i = 0; i < SIMD::numSeqs; i++) + if (currDbSeqsPos[i] != 0 && unpackedOfTest[i] <= LOWER_BOUND/2) + return 1;*/ + } else { + // There is overflow if minE == LOWER_BOUND or minF == LOWER_BOUND or maxH == UPPER_BOUND + __mxxxi minEF = SIMD::min(minE, minF); + typename SIMD::type unpackedMinEF[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedMinEF, minEF); + for (int i = 0; i < SIMD::numSeqs; i++) { + overflowed[i] = currDbSeqsPos[i] != 0 && (unpackedMinEF[i] == LOWER_BOUND + || unpackedMaxH[i] == UPPER_BOUND); + if (overflowMethod == OPAL_OVERFLOW_BUCKETS && overflowed[i]) { + // In buckets method, we stop calculation when overflow is detected. + return OPAL_ERR_OVERFLOW; + } + } + } + for (int i = 0; i < SIMD::numSeqs; i++) { + overflowDetected = overflowDetected || overflowed[i]; + } + overflowOccured = overflowOccured || overflowDetected; + // ---------------------------------------------------------------------- // + + // ------------------ Store end location of best score ------------------ // + if (searchType != OPAL_SEARCH_SCORE && (MODE == OPAL_MODE_HW || MODE == OPAL_MODE_OV)) { + // Determine the column of best score. + __mxxxi greater = SIMD::cmpgt(maxLastRowH, prevMaxLastRowH); + typename SIMD::type unpackedGreater[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedGreater, greater); + for (int i = 0; i < SIMD::numSeqs; i++) { + if (currDbSeqsPos[i] != 0 && !overflowed[i]) { // If not null sequence or overflowed + if (unpackedGreater[i] != 0) { + currDbSeqsBestScoreColumn[i] = dbSeqLengths[currDbSeqsIdxs[i]] - currDbSeqsLengths[i] + + columnsSinceLastSeqEnd - 1; + } + } + } + } + // ---------------------------------------------------------------------- // + + seqJustLoaded = false; + // --------------------- CHECK AND HANDLE SEQUENCE END ------------------ // + if (overflowDetected || shortestDbSeqLength == columnsSinceLastSeqEnd) { // If at least one sequence ended + shortestDbSeqLength = -1; + + // Calculate best scores + __mxxxi bestScore; + if (MODE == OPAL_MODE_OV) + bestScore = SIMD::max(maxH, maxLastRowH); // Maximum of last row and column + if (MODE == OPAL_MODE_HW) + bestScore = maxLastRowH; + if (MODE == OPAL_MODE_NW) + bestScore = H; + typename SIMD::type unpackedBestScore[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedBestScore, bestScore); + + for (int i = 0; i < SIMD::numSeqs; i++) { + if (currDbSeqsPos[i] != 0) { // If not null sequence + justLoaded[i] = false; + currDbSeqsLengths[i] -= columnsSinceLastSeqEnd; + + if (overflowed[i] || currDbSeqsLengths[i] == 0) { // If sequence ended + numEndedDbSeqs++; + if (!overflowed[i]) { + // Store result. + int dbSeqIdx = currDbSeqsIdxs[i]; + OpalSearchResult *result = results[dbSeqIdx]; + calculated[dbSeqIdx] = true; + // Set score. + opalSearchResultSetScore(result, unpackedBestScore[i]); + // Set end location. + if (searchType == OPAL_SEARCH_SCORE) { + result->endLocationQuery = -1; + result->endLocationTarget = -1; + } else { + if (MODE == OPAL_MODE_NW) { + result->endLocationQuery = queryLength - 1; + result->endLocationTarget = dbSeqLengths[dbSeqIdx] - 1; + } + if (MODE == OPAL_MODE_HW) { + result->endLocationQuery = queryLength - 1; + result->endLocationTarget = currDbSeqsBestScoreColumn[i]; + } + if (MODE == OPAL_MODE_OV) { + // This unpacking will repeat unnecessarily if there are multiple sequences + // ending at the same time, however that will happen in very rare occasions. + // TODO(martin): always unpack only once. + typename SIMD::type unpackedPrevMaxLastRowH[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedPrevMaxLastRowH, prevMaxLastRowH); + typename SIMD::type maxScore = unpackedPrevMaxLastRowH[i]; + + // If last column contains best score, determine row. + if (unpackedMaxH[i] > maxScore) { + result->endLocationTarget = dbSeqLengths[dbSeqIdx] - 1; + for (int r = 0; r < queryLength; r++) { + typename SIMD::type unpackedPrevH[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + _mmxxx_store_si((__mxxxi*)unpackedPrevH, prevHs[r]); + if (unpackedPrevH[i] > maxScore) { + result->endLocationQuery = r; + maxScore = unpackedPrevH[i]; + } + } + } else { + result->endLocationTarget = currDbSeqsBestScoreColumn[i]; + result->endLocationQuery = queryLength - 1; + } + } + } + } + // Load next sequence + if (loadNextSequence(nextDbSeqIdx, dbLength, currDbSeqsIdxs[i], currDbSeqsPos[i], + currDbSeqsLengths[i], db, dbSeqLengths, calculated, numEndedDbSeqs)) { + justLoaded[i] = seqJustLoaded = true; + } + } else { + if (currDbSeqsPos[i] != 0) + currDbSeqsPos[i]++; // If not new and not null, move for one element + } + // Update shortest sequence length if sequence is not null + if (currDbSeqsPos[i] != 0 && (shortestDbSeqLength == -1 || currDbSeqsLengths[i] < shortestDbSeqLength)) + shortestDbSeqLength = currDbSeqsLengths[i]; + } + } + //------------ Reset prevEs, prevHs, maxLastRowH(, ulH and uH) ------------// + typename SIMD::type resetMask[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); + typename SIMD::type setMask[SIMD::numSeqs] __attribute__((aligned(SIMD_REG_SIZE / 8))); // inverse of resetMask + for (int i = 0; i < SIMD::numSeqs; i++) { + resetMask[i] = justLoaded[i] ? 0 : -1; + setMask[i] = justLoaded[i] ? -1 : 0; + } + const __mxxxi resetMaskPacked = _mmxxx_load_si((__mxxxi const*)resetMask); + const __mxxxi setMaskPacked = _mmxxx_load_si((__mxxxi const*)setMask); + + // Set prevEs ended channels to LOWER_SCORE_BOUND + const __mxxxi maskedLowerScoreBoundSimd = _mmxxx_and_si(setMaskPacked, LOWER_SCORE_BOUND_SIMD); + for (int r = 0; r < queryLength; r++) { + prevEs[r] = _mmxxx_and_si(prevEs[r], resetMaskPacked); + prevEs[r] = SIMD::add(prevEs[r], maskedLowerScoreBoundSimd); + } + + // Set prevHs + for (int r = 0; r < queryLength; r++) { + prevHs[r] = _mmxxx_and_si(prevHs[r], resetMaskPacked); + if (MODE != OPAL_MODE_OV) { + if (r == 0) { + prevHs[0] = SIMD::sub(prevHs[0], _mmxxx_and_si(setMaskPacked, Q)); + } else { + prevHs[r] = SIMD::add(prevHs[r], _mmxxx_and_si(setMaskPacked, SIMD::sub(prevHs[r-1], R))); + } + } + } + + // Set ulH and uH if NW + if (MODE == OPAL_MODE_NW) { + ulH = _mmxxx_and_si(ulH, resetMaskPacked); // to 0 + // Set uH channels to -Q + R + uH = _mmxxx_and_si(uH, resetMaskPacked); + uH = SIMD::add(uH, _mmxxx_and_si(setMaskPacked, SIMD::sub(R, Q))); + } + + // Set maxLastRow ended channels to LOWER_BOUND + maxLastRowH = _mmxxx_and_si(maxLastRowH, resetMaskPacked); + maxLastRowH = SIMD::add(maxLastRowH, _mmxxx_and_si(setMaskPacked, LOWER_BOUND_SIMD)); + //-------------------------------------------------------// + + columnsSinceLastSeqEnd = 0; + } else { // If no sequences ended + // Move for one element in all sequences + for (int i = 0; i < SIMD::numSeqs; i++) + if (currDbSeqsPos[i] != 0) + currDbSeqsPos[i]++; + } + // ---------------------------------------------------------------------- // + } + + if (overflowOccured) { + return OPAL_ERR_OVERFLOW; + } + return 0; +} + +/** + * @param [in] skip If skip[i] is true, result for sequence #i will not be calculated. + * If skip is NULL, all results will be calculated. + */ +template +static int searchDatabase(unsigned char query[], int queryLength, + unsigned char** db, int dbLength, int dbSeqLengths[], + int gapOpen, int gapExt, int* scoreMatrix, int alphabetLength, + OpalSearchResult* results[], const int searchType, bool skip[], int overflowMethod) { + int resultCode = 0; + // Do buckets only if using buckets overflow method. + const int chunkSize = overflowMethod == OPAL_OVERFLOW_BUCKETS ? 1024 : dbLength; + bool* calculated = new bool[chunkSize]; + for (int startIdx = 0; startIdx < dbLength; startIdx += chunkSize) { + unsigned char** db_ = db + startIdx; + int* dbSeqLengths_ = dbSeqLengths + startIdx; + OpalSearchResult** results_ = results + startIdx; + int dbLength_ = startIdx + chunkSize >= dbLength ? dbLength - startIdx : chunkSize; + for (int i = 0; i < dbLength_; i++) { + calculated[i] = skip ? skip[i] : false; + } + resultCode = searchDatabase_< Simd, MODE > + (query, queryLength, db_, dbLength_, dbSeqLengths_, + gapOpen, gapExt, scoreMatrix, alphabetLength, results_, + searchType, calculated, overflowMethod); + if (resultCode == OPAL_ERR_OVERFLOW) { + resultCode = searchDatabase_< Simd, MODE > + (query, queryLength, db_, dbLength_, dbSeqLengths_, + gapOpen, gapExt, scoreMatrix, alphabetLength, results_, + searchType, calculated, overflowMethod); + if (resultCode == OPAL_ERR_OVERFLOW) { + resultCode = searchDatabase_< Simd, MODE > + (query, queryLength, db_, dbLength_, dbSeqLengths_, + gapOpen, gapExt, scoreMatrix, alphabetLength, results_, + searchType, calculated, overflowMethod); + if (resultCode != 0) + break; // TODO: this does not make much sense because of buckets, improve it. + } + } + } + delete[] calculated; + return resultCode; +} + + +/** + * @return Zero-based index of max element in array. If there are multiple elements with + * same value, last is returned. + */ +template +static inline T arrayMax(T array[], int length) { + assert(length > 0); + int maxElementIdx = 0; + for (int i = 1; i < length; i++) { + if (array[i] > array[maxElementIdx]) { + maxElementIdx = i; + } + } + return array[maxElementIdx]; +} + +/** + * @param length Length of gap, must be non-negative. + * @param gapOpen Penalty for gap opening (non-negative). + * @param gapExt Penalty for gap extension (non-negative). + * @return Gap penalty, as non-negative number. + */ +static int gapPenalty(int length, int gapOpen, int gapExt) { + if (length > 0) { + return gapOpen + gapExt * (length - 1); + } else { + return 0; + } +} + +/** + * Calculates bottom border of band for OV mode stop conditions. + */ +static int calculateBottomBandBorderOV(int k, int Q, int T, int Go, int Ge, int M) { + int border = 0; + + // for d <= Q - T: + border = std::max(border, std::min(Q - T, -1 * (k + Go - Ge - M * T) / Ge)); + + // for d > Q - T: + int borderCandidate = -1 * (k - M * Q + Go - Ge) / (Ge + M); + if (borderCandidate > Q - T) { + border = std::max(border, borderCandidate); + } + + return std::min(border, Q - 1); +} + +static int calculateTopBandBorderHW(int k, int Q, int T, int Go, int Ge, int M) { + int border = 0; + + // for d <= T - Q; + border = std::max(border, std::min(T - Q, -1 * (k - M * Q + Go) / Ge + 1)); + + // for d > T - Q: + int borderCandidate = -1 * (k - T * M + 2 * Go + Ge * (Q - T - 2)) / (2 * Ge + M); + if (borderCandidate > T - Q) { + border = std::max(border, borderCandidate); + } + + return std::min(border, T - 1); +} + +static int calculateBottomBandBorderHW(int k, int Q, int T, int Go, int Ge, int M) { + int border = 0; + + // for d >= Q - T: + int borderCandidate = -1 * (k + Go - Ge - Q * M) / (Ge + M); + if (borderCandidate >= Q - T) { + border = std::max(border, borderCandidate); + } + + // for d < Q - T: + if (-2 * Go - Ge * (Q - T - 2) + M * T >= k) { + border = std::max(border, Q - T - 1); + } + + return std::min(border, Q - 1); +} + +static int calculateBottomBandBorderNW(int k, int Q, int T, int Go, int Ge, int M) { + int border = 0; + + // for d > Q - T: + int borderCandidate = -1 * (k + 2 * Go - M * Q + Ge * (T - Q - 2)) / (2 * Ge + M); + if (borderCandidate > Q - T) { + border = std::max(border, borderCandidate); + } + + // for d = Q - T: + if (Q - T <= -1 * (k + Go - M * T - Ge) / Ge) { + border = std::max(border, Q - T); + } + + // for d < Q - T: + if (-2 * Go - Ge * (Q - T - 2) + M * T >= k) { + border = std::max(border, Q - T - 1); + } + + return std::min(border, Q - 1); +} + +/** + * Calculates top and bottom diagonal of band that contains all cells that could be part of any + * solution that gives score not smaller than k. This means that if we are interested only in solutions + * that give score that is not smaller than k, it is enough to calculate only cells inside that band. + * Always starts from top left corner (like NW does) no matter which mode is specified, + * and stops with regard to stop conditions of specified mode. + * @param k We are interested only in scores thar are not smaller than k. + * @param mode Alignment mode, it is used for stop conditions. + * @param Q queryLength + * @param T targetLength + * @param Go gapOpen -> non negative penalty for opening of gap. + * @param Ge gapExt -> non negative penalty for extension of gap. + * @param M Max score from score matrix. + * @return Pair where first is index of bottom diagonal(border), and second is index of top diagonal(border). + * Therefore, first value will be in [0, Q - 1], while second will be in [0, T - 1]. + * Band spans between top and bottom diagonal, including them. + * Main diagonal has index 0, diagonals above it and below both start with index 1. + * If there is no band, (-1, -1) is returned. + * + * Example of matrix where Q is 3 and T is 6, each cell is marked with index of diagonal it lies on: + * + * 012345 xxx--- + * 101234 , if bottom border is 1 and top is 2, we have band: xxxx-- + * 210123 -xxxx- + */ +static std::pair calculateBandBorders(int k, int mode, int Q, int T, int Go, int Ge, int M) { + if (mode == OPAL_MODE_OV || mode == OPAL_MODE_SW) { + // Bands for OV and SW have same conditions, so they are calculated in same way. + if (M * std::min(Q, T) >= k) { // Determine if band exists at all. + // Conditions for top and bottom band are symmetric, so logic for bottom is reused for top. + return std::make_pair(calculateBottomBandBorderOV(k, Q, T, Go, Ge, M), + calculateBottomBandBorderOV(k, T, Q, Go, Ge, M)); + } else { + return std::make_pair(-1, -1); + } + } else if (mode == OPAL_MODE_HW) { + if (M * std::min(Q, T) - gapPenalty(Q - std::min(Q, T), Go, Ge) >= k) { + return std::make_pair(calculateBottomBandBorderHW(k, Q, T, Go, Ge, M), + calculateTopBandBorderHW(k, Q, T, Go, Ge, M)); + } else { + return std::make_pair(-1, -1); + } + } else if (mode == OPAL_MODE_NW) { + if (M * std::min(Q, T) - gapPenalty(std::abs(Q - T), Go, Ge) >= k) { + // Conditions for top and bottom band are symmetric, so logic for bottom is reused for top. + return std::make_pair(calculateBottomBandBorderNW(k, Q, T, Go, Ge, M), + calculateBottomBandBorderNW(k, T, Q, Go, Ge, M)); + } else { + return std::make_pair(-1, -1); + } + } else { + assert(false); // Invalid alignment mode. + } +} + + + +/** + * Returns new sequence that is reverse of given sequence. + */ +static inline unsigned char* createReverseCopy(const unsigned char* seq, int length) { + unsigned char* rSeq = (unsigned char*) malloc(length * sizeof(unsigned char)); + for (int i = 0; i < length; i++) { + rSeq[i] = seq[length - i - 1]; + } + return rSeq; +} + +template +static inline void revertArray(T array[], int length) { + for (int i = 0; i < length / 2; i++) { + T tmp = array[i]; + array[i] = array[length - 1 - i]; + array[length - 1 - i] = tmp; + } +} + +// Here I store scores for one cell in score matrix. +class Cell { +public: + int H, E, F; + enum class Field { + H, E, F + }; +}; + +/** + * Finds alignment of two sequences, if we know scoreLimit. + * First alignment that has score greater or equal then scoreLimit will be returned. + * If there is no such alignment, behavior will be unexpected. + * Always starts from top left corner (like NW does) no matter which mode is specified, + * and stops with regard to stop conditions of specified mode. + * For example, for HW it will stop on last row, and for SW it will stop anywhere. + * Returns score, start location (which is always (0, 0)), end location and alignment. + * @param [in] query + * @param [in] queryLength + * @param [in] target + * @param [in] targetLength + * @param [in] gapOpen + * @param [in] gapExt + * @param [in] scoreMatrix + * @param [in] alphabetLength + * @param [in] scoreLimit First alignment with score greater/equal than scoreLimit is returned. + * If there is no such score, behavior is undefined. + * TODO(martin): make this function also work when max score is smaller then scoreLimit. + * @param [out] result Pointer to already allocated object is expected here. + * Score, start location, end location and alignment will be set. + * Do not forget to free() alignment! + * @param [in] mode Mode whose stop conditions will be used when finding alignment. + */ +static void findAlignment( + const unsigned char query[], const int queryLength, const unsigned char target[], const int targetLength, + const int gapOpen, const int gapExt, const int* scoreMatrix, const int alphabetLength, + const int scoreLimit, OpalSearchResult* result, const int mode) { + /* + printf("Query: "); + for (int i = 0; i < queryLength; i++) { + printf("%d ", query[i]); + } + printf("\n"); + printf("Target: "); + for (int i = 0; i < targetLength; i++) { + printf("%d ", target[i]); + } + printf("\n"); + */ + + //printf("lengths: %d %d\n", queryLength, targetLength); + + std::pair bandBorders = calculateBandBorders( + scoreLimit, mode, queryLength, targetLength, gapOpen, gapExt, + arrayMax(scoreMatrix, alphabetLength * alphabetLength)); + + assert(bandBorders.first >= 0 && bandBorders.first < queryLength); + assert(bandBorders.second >= 0 && bandBorders.second < targetLength); + //printf("band: %d %d\n", bandBorders.first, bandBorders.second); + + Cell** matrix = new Cell*[targetLength]; // NOTE: First index is column, second is row. + Cell* initialColumn = new Cell[queryLength]; + const int LOWER_SCORE_BOUND = INT_MIN + std::max(gapOpen, gapExt); + for (int r = 0; r < queryLength; r++) { + initialColumn[r].H = -1 * gapOpen - r * gapExt; + initialColumn[r].E = LOWER_SCORE_BOUND; + } + + Cell* prevColumn = initialColumn; + int maxScore = INT_MIN; // Max score so far, but only among cells that could be final. + int H = INT_MIN; // Current score. + int c; + for (c = 0; c < targetLength && maxScore < scoreLimit; c++) { + matrix[c] = new Cell[queryLength]; + + // First and last row in band for this column. + int rBandStart = std::max(0, c - bandBorders.second); + int rBandEnd = std::min(queryLength - 1, c + bandBorders.first); + + int uF, uH, ulH; + if (rBandStart == 0) { + uF = LOWER_SCORE_BOUND; + uH = -1 * gapOpen - c * gapExt; + ulH = c == 0 ? 0 : uH + gapExt; + } else { + uH = uF = LOWER_SCORE_BOUND; // Out of band, so set to -inf. + ulH = prevColumn[rBandStart - 1].H; + } + + for (int r = rBandStart; r <= rBandEnd; r++) { + int E = std::max(prevColumn[r].H - gapOpen, prevColumn[r].E - gapExt); + int F = std::max(uH - gapOpen, uF - gapExt); + int score = scoreMatrix[query[r] * alphabetLength + target[c]]; + H = std::max(E, std::max(F, ulH + score)); + /* + printf("E: %d ", E); + printf("F: %d ", F); + printf("score: %d ", score); + printf("ulH: %d ", ulH); + printf("H: %d ", H); + */ + + // If mode is SW, track max score of all cells. + // If mode is OV, track max score in last column. + if (mode == OPAL_MODE_SW + || (mode == OPAL_MODE_OV && c == targetLength - 1)) { + maxScore = std::max(maxScore, H); + } + + uF = F; + uH = H; + ulH = prevColumn[r].H; + + matrix[c][r].H = H; + matrix[c][r].E = E; + matrix[c][r].F = F; + } + + // Set all cells that are out of band to -inf. + for (int r = 0; r < rBandStart; r++) { + matrix[c][r].E = matrix[c][r].H = matrix[c][r].F = LOWER_SCORE_BOUND; + } + for (int r = rBandEnd + 1; r < queryLength; r++) { + matrix[c][r].E = matrix[c][r].H = matrix[c][r].F = LOWER_SCORE_BOUND; + } + + if (mode == OPAL_MODE_HW || mode == OPAL_MODE_OV) { + maxScore = std::max(maxScore, H); // Track max score in last row. + } + prevColumn = matrix[c]; + } + int lastColumnIdx = c - 1; + + result->startLocationTarget = 0; + result->startLocationQuery = 0; + result->scoreSet = 1; + // Determine score and end location of alignment. + switch (mode) { + case OPAL_MODE_NW: + opalSearchResultSetScore(result, H); + result->endLocationTarget = targetLength - 1; + result->endLocationQuery = queryLength - 1; + break; + case OPAL_MODE_HW: + opalSearchResultSetScore(result, maxScore); + result->endLocationTarget = lastColumnIdx; + result->endLocationQuery = queryLength - 1; + break; + case OPAL_MODE_SW: case OPAL_MODE_OV: + opalSearchResultSetScore(result, maxScore); + result->endLocationTarget = lastColumnIdx; + int r; + for (r = 0; r < queryLength && matrix[lastColumnIdx][r].H != maxScore; r++); + assert(r < queryLength); + assert(matrix[lastColumnIdx][r].H == maxScore); + result->endLocationQuery = r; + break; + default: + assert(false); + } + + // Construct alignment. + // I reserve max size possibly needed for alignment. + unsigned char* alignment = (unsigned char*) malloc( + sizeof(unsigned char) * (result->endLocationQuery + result->endLocationTarget)); + int alignmentLength = 0; + int rIdx = result->endLocationQuery; + int cIdx = result->endLocationTarget; + Cell::Field field = Cell::Field::H; // Current field type. + while (rIdx >= 0 && cIdx >= 0) { + Cell cell = matrix[cIdx][rIdx]; // Current cell. + + // Determine to which cell and which field we should go next, move, and add operation to alignment. + switch (field) { + case Cell::Field::H: + if (cell.H == cell.E) { + field = Cell::Field::E; + } else if (cell.H == cell.F) { + field = Cell::Field::F; + } else { + alignment[alignmentLength++] = (query[rIdx] == target[cIdx] ? OPAL_ALIGN_MATCH + : OPAL_ALIGN_MISMATCH); + cIdx--; rIdx--; + } + break; + case Cell::Field::E: + field = (cell.E == matrix[cIdx - 1][rIdx].H - gapOpen) ? Cell::Field::H : Cell::Field::E; + alignment[alignmentLength++] = OPAL_ALIGN_INS; + cIdx--; + break; + case Cell::Field::F: + field = (cell.F == matrix[cIdx][rIdx - 1].H - gapOpen) ? Cell::Field::H : Cell::Field::F; + alignment[alignmentLength++] = OPAL_ALIGN_DEL; + rIdx--; + break; + } + } + // I stop when matrix border is reached, so I have to add indels at start of alignment + // manually (they do not have entry in operations). Only one of these two loops will trigger. + while (rIdx >= 0) { + alignment[alignmentLength] = OPAL_ALIGN_DEL; + alignmentLength++; rIdx--; + } + while (cIdx >= 0) { + alignment[alignmentLength] = OPAL_ALIGN_INS; + alignmentLength++; cIdx--; + } + //printf("rIdx: %d, cIdx: %d\n", rIdx, cIdx); + assert(rIdx == -1 && cIdx == -1); + alignment = (unsigned char*) realloc(alignment, sizeof(unsigned char) * alignmentLength); + revertArray(alignment, alignmentLength); + // Store alignment to result. + result->alignment = alignment; + result->alignmentLength = alignmentLength; + + /* + printf("Alignment: "); + for (int j = 0; j < result->alignmentLength; j++) + printf("%d ", result->alignment[j]); + printf("\n"); + */ + + // Cleanup + delete[] initialColumn; + for (int i = 0; i <= lastColumnIdx; i++) { + delete[] matrix[i]; + } + delete[] matrix; +} + + + +extern int opalSearchDatabase( + unsigned char query[], int queryLength, + unsigned char** db, int dbLength, int dbSeqLengths[], + int gapOpen, int gapExt, int* scoreMatrix, int alphabetLength, + OpalSearchResult* results[], const int searchType, int mode, int overflowMethod) { +// A.D.: this will not happen since SIMDe always takes care of correct SIMD extensions +#if 0 +//#if !defined(__SSE4_1__) && !defined(__AVX2__) +// return OPAL_ERR_NO_SIMD_SUPPORT; +#else + // Calculate score and end location. + int status; + // Skip recalculation of already calculated sequences. + bool *skip = new bool[dbLength]; + for (int i = 0; i < dbLength; i++) { + skip[i] = (!opalSearchResultIsEmpty(*results[i]) + && (searchType == OPAL_SEARCH_SCORE + || (results[i]->endLocationQuery >= 0 && results[i]->endLocationTarget >= 0))); + } + if (mode == OPAL_MODE_NW) { + status = searchDatabase( + query, queryLength, db, dbLength, dbSeqLengths, gapOpen, gapExt, + scoreMatrix, alphabetLength, results, searchType, skip, overflowMethod); + } else if (mode == OPAL_MODE_HW) { + status = searchDatabase( + query, queryLength, db, dbLength, dbSeqLengths, gapOpen, gapExt, + scoreMatrix, alphabetLength, results, searchType, skip, overflowMethod); + } else if (mode == OPAL_MODE_OV) { + status = searchDatabase( + query, queryLength, db, dbLength, dbSeqLengths, gapOpen, gapExt, + scoreMatrix, alphabetLength, results, searchType, skip, overflowMethod); + } else if (mode == OPAL_MODE_SW) { + status = searchDatabaseSW( + query, queryLength, db, dbLength, dbSeqLengths, + gapOpen, gapExt, scoreMatrix, alphabetLength, + results, searchType, skip, overflowMethod); + } else { + status = OPAL_ERR_INVALID_MODE; + } + delete[] skip; + if (status) return status; + + if (searchType == OPAL_SEARCH_ALIGNMENT) { + // Calculate alignment of query with each database sequence. + unsigned char* const rQuery = createReverseCopy(query, queryLength); + for (int i = 0; i < dbLength; i++) { + if (mode == OPAL_MODE_SW && results[i]->score == 0) { // If it does not have alignment + results[i]->alignment = NULL; + results[i]->alignmentLength = 0; + results[i]->startLocationQuery = results[i]->startLocationTarget = -1; + results[i]->endLocationQuery = results[i]->endLocationTarget = -1; + } else { + //printf("%d %d\n", results[i]->endLocationQuery, results[i]->endLocationTarget); + // Do alignment in reverse direction. + int alignQueryLength = results[i]->endLocationQuery + 1; + unsigned char* alignQuery = rQuery + queryLength - alignQueryLength; + int alignTargetLength = results[i]->endLocationTarget + 1; + unsigned char* alignTarget = createReverseCopy(db[i], alignTargetLength); + OpalSearchResult result; + findAlignment( + alignQuery, alignQueryLength, alignTarget, alignTargetLength, + gapOpen, gapExt, scoreMatrix, alphabetLength, + results[i]->score, &result, mode); + //printf("%d %d\n", results[i]->score, result.score); + assert(results[i]->score == result.score); + // Translate results. + results[i]->startLocationQuery = alignQueryLength - result.endLocationQuery - 1; + results[i]->startLocationTarget = alignTargetLength - result.endLocationTarget - 1; + results[i]->alignmentLength = result.alignmentLength; + results[i]->alignment = result.alignment; + revertArray(results[i]->alignment, results[i]->alignmentLength); + free(alignTarget); + } + } + free(rQuery); + } else { + for (int i = 0; i < dbLength; i++) { + results[i]->alignment = NULL; + results[i]->alignmentLength = -1; + results[i]->startLocationQuery = -1; + results[i]->startLocationTarget = -1; + } + } + + return 0; +#endif +} + + +extern int opalSearchDatabaseCharSW( + unsigned char query[], int queryLength, unsigned char** db, int dbLength, + int dbSeqLengths[], int gapOpen, int gapExt, int* scoreMatrix, + int alphabetLength, OpalSearchResult* results[]) { +#if !defined(__SSE4_1__) && !defined(__AVX2__) + return OPAL_ERR_NO_SIMD_SUPPORT; +#else + bool* calculated = new bool[dbLength]; + for (int i = 0; i < dbLength; i++) { + calculated[i] = false; + } + int resultCode = searchDatabaseSW_< SimdSW >( + query, queryLength, db, dbLength, dbSeqLengths, gapOpen, gapExt, + scoreMatrix, alphabetLength, results, OPAL_SEARCH_SCORE, calculated, + OPAL_OVERFLOW_SIMPLE); + for (int i = 0; i < dbLength; i++) { + if (!calculated[i]) { + results[i]->score = -1; + results[i]->scoreSet = 0; + } + } + delete[] calculated; + return resultCode; +#endif +} + + +extern void opalInitSearchResult(OpalSearchResult* result) { + result->scoreSet = 0; + result->startLocationTarget = result->startLocationQuery = -1; + result->endLocationTarget = result->endLocationQuery = -1; + result->alignment = NULL; + result->alignmentLength = 0; +} + +extern int opalSearchResultIsEmpty(const OpalSearchResult result) { + return !result.scoreSet; +} + +extern void opalSearchResultSetScore(OpalSearchResult* result, int score) { + result->scoreSet = 1; + result->score = score; +} diff --git a/source/opal/opal.h b/source/opal/opal.h new file mode 100644 index 00000000..df7eb32f --- /dev/null +++ b/source/opal/opal.h @@ -0,0 +1,171 @@ +#ifndef OPAL_H +#define OPAL_H + +/*********************************************************************************** + * - adapts score type and reports overflow if score does not fit in int + * - calculating column by column (not 4 of them at once) + * - db sequences are not padded + * - using saturation arithmetic when possible + * - works for SSE4.1 and higher + *************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +// Error codes +#define OPAL_ERR_OVERFLOW 1 //!< Returned when score overflow happens. Happens only if score can't fit in int. +#define OPAL_ERR_NO_SIMD_SUPPORT 2 //!< Returned if available SIMD is not SSE4.1 or higher. +#define OPAL_ERR_INVALID_MODE 3 //!< Returned when given mode is invalid. + +// Modes +#define OPAL_MODE_NW 0 +#define OPAL_MODE_HW 1 +#define OPAL_MODE_OV 2 +#define OPAL_MODE_SW 3 + +// Overflow handling +#define OPAL_OVERFLOW_SIMPLE 0 +#define OPAL_OVERFLOW_BUCKETS 1 + +// Search types +#define OPAL_SEARCH_SCORE 0 //!< Search finds only score -> it is the fastest search. +#define OPAL_SEARCH_SCORE_END 1 //!< Search finds score and end location of alignment. +#define OPAL_SEARCH_ALIGNMENT 2 //!< Search finds score, start and end location of alignment and alignment. + +// Alignment operations +#define OPAL_ALIGN_MATCH 0 //!< Match. +#define OPAL_ALIGN_DEL 1 //!< Deletion from query (insertion to target). +#define OPAL_ALIGN_INS 2 //!< Insertion to query (deletion from target). +#define OPAL_ALIGN_MISMATCH 3 //!< Mismatch. + + /** + * Contains score and alignment information. + * If there are multiple possible alignments, one whose end + * has smallest position in target and then smallest position in row is used. + */ + struct OpalSearchResult { + int scoreSet; //!< If 1, result contains at least score. If 0, whole result is empty. + int score; + + //!< 0-indexed position in target where aligment ends. -1 if not set. + int endLocationTarget; + //!< 0-indexed position in query where aligment ends. -1 if not set. + int endLocationQuery; + + //!< 0-indexed position in target where alignment starts. -1 if not set. + int startLocationTarget; + //!< 0-indexed position in query where alignment starts. -1 if not set. + int startLocationQuery; + + /** + * Alignment is sequence of operations: + * - OPAL_ALIGN_MATCH stands for match. + * - OPAL_ALIGN_DEL stands for deletion from query (insertion to target). + * - OPAL_ALIGN_INS stands for insertion to query (deletion from target). + * - OPAL_ALIGN_MISMATCH stands for mismatch. + * Alignment aligns query to target from begining of query till end of query. + * If gaps are not penalized, they are not in alignment. + * Needed memory is allocated and given pointer is set to it. + * Important: Do not forget to free memory allocated for alignment! Use free(). + */ + unsigned char* alignment; //!< NULL if there is no alignment. + int alignmentLength; //!< 0 if there is no alignment. + }; + + /** + * Initializes result to empty result. + * Use this to initialize result object for first time, or to reset it. + * If reseting it, make sure you free alignment if you do not need it anymore. + * @param result + */ + void opalInitSearchResult(OpalSearchResult* result); + + /** + * @return 1 if result is empty, 0 if not (has at least score). + */ + int opalSearchResultIsEmpty(const OpalSearchResult result); + + void opalSearchResultSetScore(OpalSearchResult* result, int score); + + + /** + * Compares query sequence with each database sequence and returns similarity scores. + * Uses one of following alignment algorithms in combination with afine gaps(GOTOH): + * SW, NW, HW, OV. + * Sequences are not represented as arrays of letters, but as arrays of indices of + * letters in alphabet. For example, if alphabet is {A,C,T,G} and sequence is ACCTCAG + * it will be represented as 0112103. + * Opening of gap is penalized with gapOpen, while gap extension is penalized with + * gapExt. Therefore, gap of length n will have penalty of gapOpen + (n - 1) * gapExt. + * gapOpen, gapExt and scores from scoreMatrix must be in (INT_MIN/2, INT_MAX/2). + * Detects overflow only for SW! + * Although not crucial, sorting database sequences ascending by length can give + * some extra speed. + * @param [in] query Query sequence. + * @param [in] queryLength Length of query sequence. + * @param [in] db Array of database sequences (each sequence is also an array). + * @param [in] dbLength Number of database sequences. + * @param [in] dbSeqLengths Array of lengths of database sequences. + * @param [in] gapOpen Non-negative penalty for gap opening. + * @param [in] gapExt Non-negative penalty for gap extension. + * @param [in] scoreMatrix Matrix of dimensions (alphabetLength, alphabetLength). + * It is array of length alphabetLength * alphabetLength, where memory is organized + * row by row: row0row1row2...rowN. + * When there is a (mis)match of element Q from query and element T from target, + * its score is read from scoreMatrix[Q * alphabetLength + T]. + * @param [in] alphabetLength + * @param [in|out] results Results of search are written here, for each sequence. + * If a result has score and end location already calculated, they will not be + * calculated again, and if you are searching for alignment, they will be used + * to find alignment (that way you can reuse previous result). + * If you provide score and end location that are incorrect, behavior is undefined. + * @param [in] searchType Defines what type of search will be conducted. + * OPAL_SEARCH_SCORE: find score. + * OPAL_SEARCH_SCORE_END: find score and end location. + * OPAL_SEARCH_ALIGNMENT: find score, end location, start location and alignment. + * Finding of alignment takes significant amount of time and memory. + * @param [in] mode Mode of alignment, different mode means different algorithm. + * OPAL_MODE_NW: global alignment (Needleman-Wunsch) + * OPAL_MODE_HW: semi-global. Gap at query start and gap at query end + * are not penalized. + * DBSEQ + * _QUERY_ + * OPAL_MODE_OV: semi-global. Gap at query start, gap at query end, + * gap at dbseq start and gap at dbseq end are not penalized. + * _DBSEQ_ + * _QUERY_ + * OPAL_MODE_SW: local alignment (Smith-Waterman) + * @param [in] overflowMethod Method that defines behavior regarding overflows. + * OPAL_OVERFLOW_SIMPLE: all sequences are first calculated using + * char precision, those that overflowed are then calculated using + * short precision, and those that overflowed again are calculated + * using integer precision. + * OPAL_OVERFLOW_BUCKETS: database is divided into buckets and each + * bucket is calculated independently. When overflow occurs, + * calculation is resumed with higher precision for all + * following sequences in that bucket. + * @return 0 if all okay, error code otherwise. + */ + int opalSearchDatabase( + unsigned char query[], int queryLength, unsigned char* db[], int dbLength, + int dbSeqLengths[], int gapOpen, int gapExt, int* scoreMatrix, + int alphabetLength, OpalSearchResult* results[], + const int searchType, int mode, int overflowMethod); + + /** + * Same like opalSearchDatabase, with few small differences: + * - uses char for score representation + * - works in OPAL_OVERFLOW_SIMPLE mode: does not stop on overflow + * - if sequence i overflows, sequence[i] is set to -1 + */ + int opalSearchDatabaseCharSW( + unsigned char query[], int queryLength, unsigned char** db, int dbLength, + int dbSeqLengths[], int gapOpen, int gapExt, int* scoreMatrix, + int alphabetLength, OpalSearchResult* results[]); + +#ifdef __cplusplus +} +#endif + +#endif /* OPAL_H */ diff --git a/source/opal/simde_avx2.h b/source/opal/simde_avx2.h new file mode 100644 index 00000000..ec6a9a87 --- /dev/null +++ b/source/opal/simde_avx2.h @@ -0,0 +1,37990 @@ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/avx2.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2018-2020 Evan Nemerson + * 2019-2020 Michael R. Crusoe + * 2020 Himanshi Mathur + * 2020 Hidayat Khan + */ + +#if !defined(SIMDE_X86_AVX2_H) +#define SIMDE_X86_AVX2_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/avx.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2018-2020 Evan Nemerson + * 2020 Michael R. Crusoe + */ + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/sse.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + * 2015-2017 John W. Ratcliff + * 2015 Brandon Rowlett + * 2015 Ken Fast + */ + +#if !defined(SIMDE_X86_SSE_H) +#define SIMDE_X86_SSE_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/mmx.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +#if !defined(SIMDE_X86_MMX_H) +#define SIMDE_X86_MMX_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-common.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +#if !defined(SIMDE_COMMON_H) +#define SIMDE_COMMON_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/hedley.h :: */ +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(HEDLEY_VERSION) || (HEDLEY_VERSION < 15) +#if defined(HEDLEY_VERSION) +# undef HEDLEY_VERSION +#endif +#define HEDLEY_VERSION 15 + +#if defined(HEDLEY_STRINGIFY_EX) +# undef HEDLEY_STRINGIFY_EX +#endif +#define HEDLEY_STRINGIFY_EX(x) #x + +#if defined(HEDLEY_STRINGIFY) +# undef HEDLEY_STRINGIFY +#endif +#define HEDLEY_STRINGIFY(x) HEDLEY_STRINGIFY_EX(x) + +#if defined(HEDLEY_CONCAT_EX) +# undef HEDLEY_CONCAT_EX +#endif +#define HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(HEDLEY_CONCAT) +# undef HEDLEY_CONCAT +#endif +#define HEDLEY_CONCAT(a,b) HEDLEY_CONCAT_EX(a,b) + +#if defined(HEDLEY_CONCAT3_EX) +# undef HEDLEY_CONCAT3_EX +#endif +#define HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(HEDLEY_CONCAT3) +# undef HEDLEY_CONCAT3 +#endif +#define HEDLEY_CONCAT3(a,b,c) HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(HEDLEY_VERSION_ENCODE) +# undef HEDLEY_VERSION_ENCODE +#endif +#define HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(HEDLEY_VERSION_DECODE_MAJOR) +# undef HEDLEY_VERSION_DECODE_MAJOR +#endif +#define HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(HEDLEY_VERSION_DECODE_MINOR) +# undef HEDLEY_VERSION_DECODE_MINOR +#endif +#define HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(HEDLEY_VERSION_DECODE_REVISION) +# undef HEDLEY_VERSION_DECODE_REVISION +#endif +#define HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(HEDLEY_GNUC_VERSION) +# undef HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) +# define HEDLEY_GNUC_VERSION HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) +# define HEDLEY_GNUC_VERSION HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(HEDLEY_GNUC_VERSION_CHECK) +# undef HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(HEDLEY_GNUC_VERSION) +# define HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (HEDLEY_GNUC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_MSVC_VERSION) +# undef HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) +# define HEDLEY_MSVC_VERSION HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) +# define HEDLEY_MSVC_VERSION HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) +# define HEDLEY_MSVC_VERSION HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(HEDLEY_MSVC_VERSION_CHECK) +# undef HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(HEDLEY_MSVC_VERSION) +# define HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +# define HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) +# define HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else +# define HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(HEDLEY_INTEL_VERSION) +# undef HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) +# define HEDLEY_INTEL_VERSION HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) +# define HEDLEY_INTEL_VERSION HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(HEDLEY_INTEL_VERSION_CHECK) +# undef HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(HEDLEY_INTEL_VERSION) +# define HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (HEDLEY_INTEL_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_INTEL_CL_VERSION) +# undef HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) +# define HEDLEY_INTEL_CL_VERSION HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(HEDLEY_INTEL_CL_VERSION_CHECK) +# undef HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(HEDLEY_INTEL_CL_VERSION) +# define HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (HEDLEY_INTEL_CL_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_PGI_VERSION) +# undef HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) +# define HEDLEY_PGI_VERSION HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(HEDLEY_PGI_VERSION_CHECK) +# undef HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(HEDLEY_PGI_VERSION) +# define HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (HEDLEY_PGI_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_SUNPRO_VERSION) +# undef HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) +# define HEDLEY_SUNPRO_VERSION HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) +# define HEDLEY_SUNPRO_VERSION HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) +# define HEDLEY_SUNPRO_VERSION HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) +# define HEDLEY_SUNPRO_VERSION HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(HEDLEY_SUNPRO_VERSION_CHECK) +# undef HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(HEDLEY_SUNPRO_VERSION) +# define HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (HEDLEY_SUNPRO_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_EMSCRIPTEN_VERSION) +# undef HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) +# define HEDLEY_EMSCRIPTEN_VERSION HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(HEDLEY_EMSCRIPTEN_VERSION_CHECK) +# undef HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(HEDLEY_EMSCRIPTEN_VERSION) +# define HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (HEDLEY_EMSCRIPTEN_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_ARM_VERSION) +# undef HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) +# define HEDLEY_ARM_VERSION HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) +# define HEDLEY_ARM_VERSION HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(HEDLEY_ARM_VERSION_CHECK) +# undef HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(HEDLEY_ARM_VERSION) +# define HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (HEDLEY_ARM_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_IBM_VERSION) +# undef HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) +# define HEDLEY_IBM_VERSION HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) +# define HEDLEY_IBM_VERSION HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) +# define HEDLEY_IBM_VERSION HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(HEDLEY_IBM_VERSION_CHECK) +# undef HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(HEDLEY_IBM_VERSION) +# define HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (HEDLEY_IBM_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_VERSION) +# undef HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +# if (__TI_COMPILER_VERSION__ >= 16000000) +# define HEDLEY_TI_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +# endif +#endif + +#if defined(HEDLEY_TI_VERSION_CHECK) +# undef HEDLEY_TI_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_VERSION) +# define HEDLEY_TI_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_CL2000_VERSION) +# undef HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) +# define HEDLEY_TI_CL2000_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(HEDLEY_TI_CL2000_VERSION_CHECK) +# undef HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_CL2000_VERSION) +# define HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_CL2000_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_CL430_VERSION) +# undef HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) +# define HEDLEY_TI_CL430_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(HEDLEY_TI_CL430_VERSION_CHECK) +# undef HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_CL430_VERSION) +# define HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_CL430_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_ARMCL_VERSION) +# undef HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) +# define HEDLEY_TI_ARMCL_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(HEDLEY_TI_ARMCL_VERSION_CHECK) +# undef HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_ARMCL_VERSION) +# define HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_ARMCL_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_CL6X_VERSION) +# undef HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) +# define HEDLEY_TI_CL6X_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(HEDLEY_TI_CL6X_VERSION_CHECK) +# undef HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_CL6X_VERSION) +# define HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_CL6X_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_CL7X_VERSION) +# undef HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) +# define HEDLEY_TI_CL7X_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(HEDLEY_TI_CL7X_VERSION_CHECK) +# undef HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_CL7X_VERSION) +# define HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_CL7X_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TI_CLPRU_VERSION) +# undef HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) +# define HEDLEY_TI_CLPRU_VERSION HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(HEDLEY_TI_CLPRU_VERSION_CHECK) +# undef HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(HEDLEY_TI_CLPRU_VERSION) +# define HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (HEDLEY_TI_CLPRU_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_CRAY_VERSION) +# undef HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) +# if defined(_RELEASE_PATCHLEVEL) +# define HEDLEY_CRAY_VERSION HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) +# else +# define HEDLEY_CRAY_VERSION HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) +# endif +#endif + +#if defined(HEDLEY_CRAY_VERSION_CHECK) +# undef HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(HEDLEY_CRAY_VERSION) +# define HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (HEDLEY_CRAY_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_IAR_VERSION) +# undef HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) +# if __VER__ > 1000 +# define HEDLEY_IAR_VERSION HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) +# else +# define HEDLEY_IAR_VERSION HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) +# endif +#endif + +#if defined(HEDLEY_IAR_VERSION_CHECK) +# undef HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(HEDLEY_IAR_VERSION) +# define HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (HEDLEY_IAR_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_TINYC_VERSION) +# undef HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) +# define HEDLEY_TINYC_VERSION HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(HEDLEY_TINYC_VERSION_CHECK) +# undef HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(HEDLEY_TINYC_VERSION) +# define HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (HEDLEY_TINYC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_DMC_VERSION) +# undef HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) +# define HEDLEY_DMC_VERSION HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(HEDLEY_DMC_VERSION_CHECK) +# undef HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(HEDLEY_DMC_VERSION) +# define HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (HEDLEY_DMC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_COMPCERT_VERSION) +# undef HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) +# define HEDLEY_COMPCERT_VERSION HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(HEDLEY_COMPCERT_VERSION_CHECK) +# undef HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(HEDLEY_COMPCERT_VERSION) +# define HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (HEDLEY_COMPCERT_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_PELLES_VERSION) +# undef HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) +# define HEDLEY_PELLES_VERSION HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(HEDLEY_PELLES_VERSION_CHECK) +# undef HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(HEDLEY_PELLES_VERSION) +# define HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (HEDLEY_PELLES_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_MCST_LCC_VERSION) +# undef HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) +# define HEDLEY_MCST_LCC_VERSION HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(HEDLEY_MCST_LCC_VERSION_CHECK) +# undef HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(HEDLEY_MCST_LCC_VERSION) +# define HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (HEDLEY_MCST_LCC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_GCC_VERSION) +# undef HEDLEY_GCC_VERSION +#endif +#if \ + defined(HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(HEDLEY_INTEL_VERSION) && \ + !defined(HEDLEY_PGI_VERSION) && \ + !defined(HEDLEY_ARM_VERSION) && \ + !defined(HEDLEY_CRAY_VERSION) && \ + !defined(HEDLEY_TI_VERSION) && \ + !defined(HEDLEY_TI_ARMCL_VERSION) && \ + !defined(HEDLEY_TI_CL430_VERSION) && \ + !defined(HEDLEY_TI_CL2000_VERSION) && \ + !defined(HEDLEY_TI_CL6X_VERSION) && \ + !defined(HEDLEY_TI_CL7X_VERSION) && \ + !defined(HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(HEDLEY_MCST_LCC_VERSION) +# define HEDLEY_GCC_VERSION HEDLEY_GNUC_VERSION +#endif + +#if defined(HEDLEY_GCC_VERSION_CHECK) +# undef HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(HEDLEY_GCC_VERSION) +# define HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (HEDLEY_GCC_VERSION >= HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +# define HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(HEDLEY_HAS_ATTRIBUTE) +# undef HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(HEDLEY_IAR_VERSION) || HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_ATTRIBUTE) +# undef HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +# define HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_HAS_ATTRIBUTE(attribute) +#else +# define HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_ATTRIBUTE) +# undef HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +# define HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_HAS_ATTRIBUTE(attribute) +#else +# define HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_HAS_CPP_ATTRIBUTE) +# undef HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(HEDLEY_SUNPRO_VERSION) || HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) +# define HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else +# define HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(HEDLEY_HAS_CPP_ATTRIBUTE_NS) +# undef HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) +# define HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(HEDLEY_PGI_VERSION) && \ + !defined(HEDLEY_IAR_VERSION) && \ + (!defined(HEDLEY_SUNPRO_VERSION) || HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19,20,0)) +# define HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else +# define HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) +# undef HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) +# define HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else +# define HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_CPP_ATTRIBUTE) +# undef HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) +# define HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else +# define HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_HAS_BUILTIN) +# undef HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) +# define HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else +# define HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_BUILTIN) +# undef HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) +# define HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else +# define HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_BUILTIN) +# undef HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) +# define HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else +# define HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_HAS_FEATURE) +# undef HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) +# define HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else +# define HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_FEATURE) +# undef HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) +# define HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else +# define HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_FEATURE) +# undef HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) +# define HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else +# define HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_HAS_EXTENSION) +# undef HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) +# define HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else +# define HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_EXTENSION) +# undef HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) +# define HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else +# define HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_EXTENSION) +# undef HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) +# define HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else +# define HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_HAS_DECLSPEC_ATTRIBUTE) +# undef HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +# define HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else +# define HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) +# undef HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +# define HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else +# define HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) +# undef HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +# define HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else +# define HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_HAS_WARNING) +# undef HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) +# define HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else +# define HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(HEDLEY_GNUC_HAS_WARNING) +# undef HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) +# define HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else +# define HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_GCC_HAS_WARNING) +# undef HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) +# define HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else +# define HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) +# define HEDLEY_PRAGMA(value) _Pragma(#value) +#elif HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define HEDLEY_PRAGMA(value) __pragma(value) +#else +# define HEDLEY_PRAGMA(value) +#endif + +#if defined(HEDLEY_DIAGNOSTIC_PUSH) +# undef HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(HEDLEY_DIAGNOSTIC_POP) +# undef HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) +# define HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +# define HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +# define HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif HEDLEY_GCC_VERSION_CHECK(4,6,0) +# define HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +# define HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) +# define HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif HEDLEY_ARM_VERSION_CHECK(5,6,0) +# define HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") +# define HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) +# define HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") +# define HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif HEDLEY_PELLES_VERSION_CHECK(2,90,0) +# define HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +# define HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else +# define HEDLEY_DIAGNOSTIC_PUSH +# define HEDLEY_DIAGNOSTIC_POP +#endif + +/* HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) +# undef HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if HEDLEY_HAS_WARNING("-Wc++98-compat") +# if HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + HEDLEY_DIAGNOSTIC_POP +# else +# define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) +# define HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(HEDLEY_CONST_CAST) +# undef HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + HEDLEY_HAS_WARNING("-Wcast-qual") || \ + HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + HEDLEY_DIAGNOSTIC_PUSH \ + HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(HEDLEY_REINTERPRET_CAST) +# undef HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) +# define HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else +# define HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(HEDLEY_STATIC_CAST) +# undef HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) +# define HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else +# define HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(HEDLEY_CPP_CAST) +# undef HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if HEDLEY_HAS_WARNING("-Wold-style-cast") +# define HEDLEY_CPP_CAST(T, expr) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + HEDLEY_DIAGNOSTIC_POP +# elif HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define HEDLEY_CPP_CAST(T, expr) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + HEDLEY_DIAGNOSTIC_POP +# else +# define HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) +# undef HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if HEDLEY_HAS_WARNING("-Wdeprecated-declarations") +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif HEDLEY_PGI_VERSION_CHECK(20,7,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif HEDLEY_PGI_VERSION_CHECK(17,10,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif HEDLEY_GCC_VERSION_CHECK(4,3,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif HEDLEY_PELLES_VERSION_CHECK(2,90,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else +# define HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) +# undef HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif HEDLEY_PGI_VERSION_CHECK(17,10,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif HEDLEY_GCC_VERSION_CHECK(4,3,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) +# undef HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if HEDLEY_HAS_WARNING("-Wunknown-attributes") +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif HEDLEY_GCC_VERSION_CHECK(4,6,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif HEDLEY_INTEL_VERSION_CHECK(17,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif HEDLEY_MSVC_VERSION_CHECK(19,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif HEDLEY_PGI_VERSION_CHECK(20,7,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif HEDLEY_PGI_VERSION_CHECK(17,10,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else +# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) +# undef HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if HEDLEY_HAS_WARNING("-Wcast-qual") +# define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif HEDLEY_GCC_VERSION_CHECK(3,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else +# define HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) +# undef HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if HEDLEY_HAS_WARNING("-Wunused-function") +# define HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif HEDLEY_GCC_VERSION_CHECK(3,4,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif HEDLEY_MSVC_VERSION_CHECK(1,0,0) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else +# define HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(HEDLEY_DEPRECATED) +# undef HEDLEY_DEPRECATED +#endif +#if defined(HEDLEY_DEPRECATED_FOR) +# undef HEDLEY_DEPRECATED_FOR +#endif +#if \ + HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) +# define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(HEDLEY_IAR_VERSION)) || \ + HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) +# define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) +# define HEDLEY_DEPRECATED(since) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) +# define HEDLEY_DEPRECATED_FOR(since, replacement) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) +# define HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_DEPRECATED(since) __declspec(deprecated) +# define HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_DEPRECATED(since) _Pragma("deprecated") +# define HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else +# define HEDLEY_DEPRECATED(since) +# define HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(HEDLEY_UNAVAILABLE) +# undef HEDLEY_UNAVAILABLE +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(warning) || \ + HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else +# define HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(HEDLEY_WARN_UNUSED_RESULT) +# undef HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(HEDLEY_WARN_UNUSED_RESULT_MSG) +# undef HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +# define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) +# define HEDLEY_WARN_UNUSED_RESULT HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +# define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) +# define HEDLEY_WARN_UNUSED_RESULT HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +# define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ +# define HEDLEY_WARN_UNUSED_RESULT _Check_return_ +# define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else +# define HEDLEY_WARN_UNUSED_RESULT +# define HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(HEDLEY_SENTINEL) +# undef HEDLEY_SENTINEL +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else +# define HEDLEY_SENTINEL(position) +#endif + +#if defined(HEDLEY_NO_RETURN) +# undef HEDLEY_NO_RETURN +#endif +#if HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_NO_RETURN __noreturn +#elif \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +# define HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +# define HEDLEY_NO_RETURN HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_NO_RETURN __declspec(noreturn) +#elif HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) +# define HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) +# define HEDLEY_NO_RETURN __attribute((noreturn)) +#elif HEDLEY_PELLES_VERSION_CHECK(9,0,0) +# define HEDLEY_NO_RETURN __declspec(noreturn) +#else +# define HEDLEY_NO_RETURN +#endif + +#if defined(HEDLEY_NO_ESCAPE) +# undef HEDLEY_NO_ESCAPE +#endif +#if HEDLEY_HAS_ATTRIBUTE(noescape) +# define HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else +# define HEDLEY_NO_ESCAPE +#endif + +#if defined(HEDLEY_UNREACHABLE) +# undef HEDLEY_UNREACHABLE +#endif +#if defined(HEDLEY_UNREACHABLE_RETURN) +# undef HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(HEDLEY_ASSUME) +# undef HEDLEY_ASSUME +#endif +#if \ + HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_ASSUME(expr) __assume(expr) +#elif HEDLEY_HAS_BUILTIN(__builtin_assume) +# define HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) +# if defined(__cplusplus) +# define HEDLEY_ASSUME(expr) std::_nassert(expr) +# else +# define HEDLEY_ASSUME(expr) _nassert(expr) +# endif +#endif +#if \ + (HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(HEDLEY_ARM_VERSION))) || \ + HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(HEDLEY_ASSUME) +# define HEDLEY_UNREACHABLE() HEDLEY_ASSUME(0) +#endif +#if !defined(HEDLEY_ASSUME) +# if defined(HEDLEY_UNREACHABLE) +# define HEDLEY_ASSUME(expr) HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (HEDLEY_UNREACHABLE(), 1))) +# else +# define HEDLEY_ASSUME(expr) HEDLEY_STATIC_CAST(void, expr) +# endif +#endif +#if defined(HEDLEY_UNREACHABLE) +# if \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) +# define HEDLEY_UNREACHABLE_RETURN(value) return (HEDLEY_STATIC_CAST(void, HEDLEY_ASSUME(0)), (value)) +# else +# define HEDLEY_UNREACHABLE_RETURN(value) HEDLEY_UNREACHABLE() +# endif +#else +# define HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(HEDLEY_UNREACHABLE) +# define HEDLEY_UNREACHABLE() HEDLEY_ASSUME(0) +#endif + +HEDLEY_DIAGNOSTIC_PUSH +#if HEDLEY_HAS_WARNING("-Wpedantic") +# pragma clang diagnostic ignored "-Wpedantic" +#endif +#if HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) +# if defined(__clang__) +# pragma clang diagnostic ignored "-Wvariadic-macros" +# elif defined(HEDLEY_GCC_VERSION) +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# endif +#endif +#if defined(HEDLEY_NON_NULL) +# undef HEDLEY_NON_NULL +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) +# define HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else +# define HEDLEY_NON_NULL(...) +#endif +HEDLEY_DIAGNOSTIC_POP + +#if defined(HEDLEY_PRINTF_FORMAT) +# undef HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) +# define HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) +# define HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + HEDLEY_HAS_ATTRIBUTE(format) || \ + HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif HEDLEY_PELLES_VERSION_CHECK(6,0,0) +# define HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else +# define HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(HEDLEY_CONSTEXPR) +# undef HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) +# if __cplusplus >= 201103L +# define HEDLEY_CONSTEXPR HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) +# endif +#endif +#if !defined(HEDLEY_CONSTEXPR) +# define HEDLEY_CONSTEXPR +#endif + +#if defined(HEDLEY_PREDICT) +# undef HEDLEY_PREDICT +#endif +#if defined(HEDLEY_LIKELY) +# undef HEDLEY_LIKELY +#endif +#if defined(HEDLEY_UNLIKELY) +# undef HEDLEY_UNLIKELY +#endif +#if defined(HEDLEY_UNPREDICTABLE) +# undef HEDLEY_UNPREDICTABLE +#endif +#if HEDLEY_HAS_BUILTIN(__builtin_unpredictable) +# define HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(HEDLEY_PGI_VERSION)) || \ + HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(HEDLEY_INTEL_CL_VERSION)) || \ + HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (HEDLEY_STATIC_CAST(void, expected), (expr))) +# define HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define HEDLEY_PREDICT(expr, expected, probability) (HEDLEY_STATIC_CAST(void, expected), (expr)) +# define HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define HEDLEY_LIKELY(expr) (!!(expr)) +# define HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(HEDLEY_UNPREDICTABLE) +# define HEDLEY_UNPREDICTABLE(expr) HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(HEDLEY_MALLOC) +# undef HEDLEY_MALLOC +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(malloc) || \ + HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_MALLOC __attribute__((__malloc__)) +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_MALLOC __declspec(restrict) +#else +# define HEDLEY_MALLOC +#endif + +#if defined(HEDLEY_PURE) +# undef HEDLEY_PURE +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(pure) || \ + HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_PURE __attribute__((__pure__)) +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define HEDLEY_PURE +#endif + +#if defined(HEDLEY_CONST) +# undef HEDLEY_CONST +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(const) || \ + HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_CONST __attribute__((__const__)) +#elif \ + HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define HEDLEY_CONST _Pragma("no_side_effect") +#else +# define HEDLEY_CONST HEDLEY_PURE +#endif + +#if defined(HEDLEY_RESTRICT) +# undef HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) +# define HEDLEY_RESTRICT restrict +#elif \ + HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_RESTRICT __restrict +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) +# define HEDLEY_RESTRICT _Restrict +#else +# define HEDLEY_RESTRICT +#endif + +#if defined(HEDLEY_INLINE) +# undef HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) +# define HEDLEY_INLINE inline +#elif \ + defined(HEDLEY_GCC_VERSION) || \ + HEDLEY_ARM_VERSION_CHECK(6,2,0) +# define HEDLEY_INLINE __inline__ +#elif \ + HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_INLINE __inline +#else +# define HEDLEY_INLINE +#endif + +#if defined(HEDLEY_ALWAYS_INLINE) +# undef HEDLEY_ALWAYS_INLINE +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) HEDLEY_INLINE +#elif \ + HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define HEDLEY_ALWAYS_INLINE HEDLEY_INLINE +#endif + +#if defined(HEDLEY_NEVER_INLINE) +# undef HEDLEY_NEVER_INLINE +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(noinline) || \ + HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_NEVER_INLINE __declspec(noinline) +#elif HEDLEY_PGI_VERSION_CHECK(10,2,0) +# define HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) +# define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) +# define HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif HEDLEY_PELLES_VERSION_CHECK(9,0,0) +# define HEDLEY_NEVER_INLINE __declspec(noinline) +#else +# define HEDLEY_NEVER_INLINE +#endif + +#if defined(HEDLEY_PRIVATE) +# undef HEDLEY_PRIVATE +#endif +#if defined(HEDLEY_PUBLIC) +# undef HEDLEY_PUBLIC +#endif +#if defined(HEDLEY_IMPORT) +# undef HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define HEDLEY_PRIVATE +# define HEDLEY_PUBLIC __declspec(dllexport) +# define HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + HEDLEY_HAS_ATTRIBUTE(visibility) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define HEDLEY_PRIVATE +# define HEDLEY_PUBLIC +# endif +# define HEDLEY_IMPORT extern +#endif + +#if defined(HEDLEY_NO_THROW) +# undef HEDLEY_NO_THROW +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) +# define HEDLEY_NO_THROW __declspec(nothrow) +#else +# define HEDLEY_NO_THROW +#endif + +#if defined(HEDLEY_FALL_THROUGH) +# undef HEDLEY_FALL_THROUGH +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) +# define HEDLEY_FALL_THROUGH HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) +# define HEDLEY_FALL_THROUGH HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ +# define HEDLEY_FALL_THROUGH __fallthrough +#else +# define HEDLEY_FALL_THROUGH +#endif + +#if defined(HEDLEY_RETURNS_NON_NULL) +# undef HEDLEY_RETURNS_NON_NULL +#endif +#if \ + HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ +# define HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else +# define HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(HEDLEY_ARRAY_PARAM) +# undef HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(HEDLEY_PGI_VERSION) && \ + !defined(HEDLEY_TINYC_VERSION) +# define HEDLEY_ARRAY_PARAM(name) (name) +#else +# define HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(HEDLEY_IS_CONSTANT) +# undef HEDLEY_IS_CONSTANT +#endif +#if defined(HEDLEY_REQUIRE_CONSTEXPR) +# undef HEDLEY_REQUIRE_CONSTEXPR +#endif +/* HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(HEDLEY_IS_CONSTEXPR_) +# undef HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,24) +# if defined(__INTPTR_TYPE__) +# define HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +# else +# include +# define HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +# endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(HEDLEY_SUNPRO_VERSION) && \ + !defined(HEDLEY_PGI_VERSION) && \ + !defined(HEDLEY_IAR_VERSION)) || \ + (HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(HEDLEY_IAR_VERSION)) || \ + HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + HEDLEY_ARM_VERSION_CHECK(5,3,0) +# if defined(__INTPTR_TYPE__) +# define HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +# else +# include +# define HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +# endif +# elif \ + defined(HEDLEY_GCC_VERSION) || \ + defined(HEDLEY_INTEL_VERSION) || \ + defined(HEDLEY_TINYC_VERSION) || \ + defined(HEDLEY_TI_ARMCL_VERSION) || \ + HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(HEDLEY_TI_CL2000_VERSION) || \ + defined(HEDLEY_TI_CL6X_VERSION) || \ + defined(HEDLEY_TI_CL7X_VERSION) || \ + defined(HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ + ((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(HEDLEY_IS_CONSTEXPR_) +# if !defined(HEDLEY_IS_CONSTANT) +# define HEDLEY_IS_CONSTANT(expr) HEDLEY_IS_CONSTEXPR_(expr) +# endif +# define HEDLEY_REQUIRE_CONSTEXPR(expr) (HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else +# if !defined(HEDLEY_IS_CONSTANT) +# define HEDLEY_IS_CONSTANT(expr) (0) +# endif +# define HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(HEDLEY_BEGIN_C_DECLS) +# undef HEDLEY_BEGIN_C_DECLS +#endif +#if defined(HEDLEY_END_C_DECLS) +# undef HEDLEY_END_C_DECLS +#endif +#if defined(HEDLEY_C_DECL) +# undef HEDLEY_C_DECL +#endif +#if defined(__cplusplus) +# define HEDLEY_BEGIN_C_DECLS extern "C" { +# define HEDLEY_END_C_DECLS } +# define HEDLEY_C_DECL extern "C" +#else +# define HEDLEY_BEGIN_C_DECLS +# define HEDLEY_END_C_DECLS +# define HEDLEY_C_DECL +#endif + +#if defined(HEDLEY_STATIC_ASSERT) +# undef HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (HEDLEY_HAS_FEATURE(c_static_assert) && !defined(HEDLEY_INTEL_CL_VERSION)) || \ + HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_STATIC_ASSERT(expr, message) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(HEDLEY_NULL) +# undef HEDLEY_NULL +#endif +#if defined(__cplusplus) +# if __cplusplus >= 201103L +# define HEDLEY_NULL HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) +# elif defined(NULL) +# define HEDLEY_NULL NULL +# else +# define HEDLEY_NULL HEDLEY_STATIC_CAST(void*, 0) +# endif +#elif defined(NULL) +# define HEDLEY_NULL NULL +#else +# define HEDLEY_NULL ((void*) 0) +#endif + +#if defined(HEDLEY_MESSAGE) +# undef HEDLEY_MESSAGE +#endif +#if HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define HEDLEY_MESSAGE(msg) \ + HEDLEY_DIAGNOSTIC_PUSH \ + HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + HEDLEY_PRAGMA(message msg) \ + HEDLEY_DIAGNOSTIC_POP +#elif \ + HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message msg) +#elif HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(_CRI message msg) +#elif HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message(msg)) +#elif HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message(msg)) +#else +# define HEDLEY_MESSAGE(msg) +#endif + +#if defined(HEDLEY_WARNING) +# undef HEDLEY_WARNING +#endif +#if HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define HEDLEY_WARNING(msg) \ + HEDLEY_DIAGNOSTIC_PUSH \ + HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + HEDLEY_PRAGMA(clang warning msg) \ + HEDLEY_DIAGNOSTIC_POP +#elif \ + HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(GCC warning msg) +#elif \ + HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(message(msg)) +#else +# define HEDLEY_WARNING(msg) HEDLEY_MESSAGE(msg) +#endif + +#if defined(HEDLEY_REQUIRE) +# undef HEDLEY_REQUIRE +#endif +#if defined(HEDLEY_REQUIRE_MSG) +# undef HEDLEY_REQUIRE_MSG +#endif +#if HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if HEDLEY_HAS_WARNING("-Wgcc-compat") +# define HEDLEY_REQUIRE(expr) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + HEDLEY_DIAGNOSTIC_POP +# define HEDLEY_REQUIRE_MSG(expr,msg) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + HEDLEY_DIAGNOSTIC_POP +# else +# define HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define HEDLEY_REQUIRE(expr) +# define HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(HEDLEY_FLAGS) +# undef HEDLEY_FLAGS +#endif +#if HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) +# define HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else +# define HEDLEY_FLAGS +#endif + +#if defined(HEDLEY_FLAGS_CAST) +# undef HEDLEY_FLAGS_CAST +#endif +#if HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define HEDLEY_FLAGS_CAST(T, expr) HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(HEDLEY_EMPTY_BASES) +# undef HEDLEY_EMPTY_BASES +#endif +#if \ + (HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else +# define HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) +# undef HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) +# define HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else +# define HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(HEDLEY_CLANG_HAS_ATTRIBUTE) +# undef HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) +# undef HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(HEDLEY_CLANG_HAS_BUILTIN) +# undef HEDLEY_CLANG_HAS_BUILTIN +#endif +#define HEDLEY_CLANG_HAS_BUILTIN(builtin) HEDLEY_HAS_BUILTIN(builtin) + +#if defined(HEDLEY_CLANG_HAS_FEATURE) +# undef HEDLEY_CLANG_HAS_FEATURE +#endif +#define HEDLEY_CLANG_HAS_FEATURE(feature) HEDLEY_HAS_FEATURE(feature) + +#if defined(HEDLEY_CLANG_HAS_EXTENSION) +# undef HEDLEY_CLANG_HAS_EXTENSION +#endif +#define HEDLEY_CLANG_HAS_EXTENSION(extension) HEDLEY_HAS_EXTENSION(extension) + +#if defined(HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) +# undef HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(HEDLEY_CLANG_HAS_WARNING) +# undef HEDLEY_CLANG_HAS_WARNING +#endif +#define HEDLEY_CLANG_HAS_WARNING(warning) HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(HEDLEY_VERSION) || (HEDLEY_VERSION < X) */ +/* :: End ../simde/simde/hedley.h :: */ + +#define SIMDE_VERSION_MAJOR 0 +#define SIMDE_VERSION_MINOR 7 +#define SIMDE_VERSION_MICRO 3 +#define SIMDE_VERSION HEDLEY_VERSION_ENCODE(SIMDE_VERSION_MAJOR, SIMDE_VERSION_MINOR, SIMDE_VERSION_MICRO) +// Also update meson.build in the root directory of the repository + +#include +#include + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-detect-clang.h :: */ +/* Detect Clang Version + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +/* This file was originally part of SIMDe + * (). You're free to do with it as + * you please, but I do have a few small requests: + * + * * If you make improvements, please submit them back to SIMDe + * (at ) so others can + * benefit from them. + * * Please keep a link to SIMDe intact so people know where to submit + * improvements. + * * If you expose it publicly, please change the SIMDE_ prefix to + * something specific to your project. + * + * The version numbers clang exposes (in the ___clang_major__, + * __clang_minor__, and __clang_patchlevel__ macros) are unreliable. + * Vendors such as Apple will define these values to their version + * numbers; for example, "Apple Clang 4.0" is really clang 3.1, but + * __clang_major__ and __clang_minor__ are defined to 4 and 0 + * respectively, instead of 3 and 1. + * + * The solution is *usually* to use clang's feature detection macros + * () + * to determine if the feature you're interested in is available. This + * generally works well, and it should probably be the first thing you + * try. Unfortunately, it's not possible to check for everything. In + * particular, compiler bugs. + * + * This file just uses the feature checking macros to detect features + * added in specific versions of clang to identify which version of + * clang the compiler is based on. + * + * Right now it only goes back to 3.6, but I'm happy to accept patches + * to go back further. And, of course, newer versions are welcome if + * they're not already present, and if you find a way to detect a point + * release that would be great, too! + */ + +#if !defined(SIMDE_DETECT_CLANG_H) +#define SIMDE_DETECT_CLANG_H 1 + +/* Attempt to detect the upstream clang version number. I usually only + * worry about major version numbers (at least for 4.0+), but if you + * need more resolution I'm happy to accept patches that are able to + * detect minor versions as well. That said, you'll probably have a + * hard time with detection since AFAIK most minor releases don't add + * anything we can detect. */ + +#if defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION) +# if __has_warning("-Wformat-insufficient-args") +# define SIMDE_DETECT_CLANG_VERSION 120000 +# elif __has_warning("-Wimplicit-const-int-float-conversion") +# define SIMDE_DETECT_CLANG_VERSION 110000 +# elif __has_warning("-Wmisleading-indentation") +# define SIMDE_DETECT_CLANG_VERSION 100000 +# elif defined(__FILE_NAME__) +# define SIMDE_DETECT_CLANG_VERSION 90000 +# elif __has_warning("-Wextra-semi-stmt") || __has_builtin(__builtin_rotateleft32) +# define SIMDE_DETECT_CLANG_VERSION 80000 +# elif __has_warning("-Wc++98-compat-extra-semi") +# define SIMDE_DETECT_CLANG_VERSION 70000 +# elif __has_warning("-Wpragma-pack") +# define SIMDE_DETECT_CLANG_VERSION 60000 +# elif __has_warning("-Wbitfield-enum-conversion") +# define SIMDE_DETECT_CLANG_VERSION 50000 +# elif __has_attribute(diagnose_if) +# define SIMDE_DETECT_CLANG_VERSION 40000 +# elif __has_warning("-Wcomma") +# define SIMDE_DETECT_CLANG_VERSION 39000 +# elif __has_warning("-Wdouble-promotion") +# define SIMDE_DETECT_CLANG_VERSION 38000 +# elif __has_warning("-Wshift-negative-value") +# define SIMDE_DETECT_CLANG_VERSION 37000 +# elif __has_warning("-Wambiguous-ellipsis") +# define SIMDE_DETECT_CLANG_VERSION 36000 +# else +# define SIMDE_DETECT_CLANG_VERSION 1 +# endif +#endif /* defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION) */ + +/* The SIMDE_DETECT_CLANG_VERSION_CHECK macro is pretty + * straightforward; it returns true if the compiler is a derivative + * of clang >= the specified version. + * + * Since this file is often (primarily?) useful for working around bugs + * it is also helpful to have a macro which returns true if only if the + * compiler is a version of clang *older* than the specified version to + * make it a bit easier to ifdef regions to add code for older versions, + * such as pragmas to disable a specific warning. */ + +#if defined(SIMDE_DETECT_CLANG_VERSION) +# define SIMDE_DETECT_CLANG_VERSION_CHECK(major, minor, revision) (SIMDE_DETECT_CLANG_VERSION >= ((major * 10000) + (minor * 1000) + (revision))) +# define SIMDE_DETECT_CLANG_VERSION_NOT(major, minor, revision) (SIMDE_DETECT_CLANG_VERSION < ((major * 10000) + (minor * 1000) + (revision))) +#else +# define SIMDE_DETECT_CLANG_VERSION_CHECK(major, minor, revision) (0) +# define SIMDE_DETECT_CLANG_VERSION_NOT(major, minor, revision) (0) +#endif + +#endif /* !defined(SIMDE_DETECT_CLANG_H) */ +/* :: End ../simde/simde/simde-detect-clang.h :: */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-arch.h :: */ +/* Architecture detection + * Created by Evan Nemerson + * + * To the extent possible under law, the authors have waived all + * copyright and related or neighboring rights to this code. For + * details, see the Creative Commons Zero 1.0 Universal license at + * + * + * SPDX-License-Identifier: CC0-1.0 + * + * Different compilers define different preprocessor macros for the + * same architecture. This is an attempt to provide a single + * interface which is usable on any compiler. + * + * In general, a macro named SIMDE_ARCH_* is defined for each + * architecture the CPU supports. When there are multiple possible + * versions, we try to define the macro to the target version. For + * example, if you want to check for i586+, you could do something + * like: + * + * #if defined(SIMDE_ARCH_X86) && (SIMDE_ARCH_X86 >= 5) + * ... + * #endif + * + * You could also just check that SIMDE_ARCH_X86 >= 5 without checking + * if it's defined first, but some compilers may emit a warning about + * an undefined macro being used (e.g., GCC with -Wundef). + * + * This was originally created for SIMDe + * (hence the prefix), but this + * header has no dependencies and may be used anywhere. It is + * originally based on information from + * , though it + * has been enhanced with additional information. + * + * If you improve this file, or find a bug, please file the issue at + * . If you copy this into + * your project, even if you change the prefix, please keep the links + * to SIMDe intact so others know where to report issues, submit + * enhancements, and find the latest version. */ + +#if !defined(SIMDE_ARCH_H) +#define SIMDE_ARCH_H + +/* Alpha + */ +#if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# if defined(__alpha_ev6__) +# define SIMDE_ARCH_ALPHA 6 +# elif defined(__alpha_ev5__) +# define SIMDE_ARCH_ALPHA 5 +# elif defined(__alpha_ev4__) +# define SIMDE_ARCH_ALPHA 4 +# else +# define SIMDE_ARCH_ALPHA 1 +# endif +#endif +#if defined(SIMDE_ARCH_ALPHA) +# define SIMDE_ARCH_ALPHA_CHECK(version) ((version) <= SIMDE_ARCH_ALPHA) +#else +# define SIMDE_ARCH_ALPHA_CHECK(version) (0) +#endif + +/* Atmel AVR + */ +#if defined(__AVR_ARCH__) +# define SIMDE_ARCH_AVR __AVR_ARCH__ +#endif + +/* AMD64 / x86_64 + */ +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +# define SIMDE_ARCH_AMD64 1000 +#endif + +/* ARM + */ +#if defined(__ARM_ARCH_8A__) +# define SIMDE_ARCH_ARM 82 +#elif defined(__ARM_ARCH_8R__) +# define SIMDE_ARCH_ARM 81 +#elif defined(__ARM_ARCH_8__) +# define SIMDE_ARCH_ARM 80 +#elif defined(__ARM_ARCH_7S__) +# define SIMDE_ARCH_ARM 74 +#elif defined(__ARM_ARCH_7M__) +# define SIMDE_ARCH_ARM 73 +#elif defined(__ARM_ARCH_7R__) +# define SIMDE_ARCH_ARM 72 +#elif defined(__ARM_ARCH_7A__) +# define SIMDE_ARCH_ARM 71 +#elif defined(__ARM_ARCH_7__) +# define SIMDE_ARCH_ARM 70 +#elif defined(__ARM_ARCH) +# define SIMDE_ARCH_ARM (__ARM_ARCH * 10) +#elif defined(_M_ARM) +# define SIMDE_ARCH_ARM (_M_ARM * 10) +#elif defined(__arm__) || defined(__thumb__) || defined(__TARGET_ARCH_ARM) || defined(_ARM) || defined(_M_ARM) || defined(_M_ARM) +# define SIMDE_ARCH_ARM 1 +#endif +#if defined(SIMDE_ARCH_ARM ) +# define SIMDE_ARCH_ARM_CHECK(version) ((version) <= SIMDE_ARCH_ARM) +#else +# define SIMDE_ARCH_ARM_CHECK(version) (0) +#endif + +/* AArch64 + */ +#if defined(__aarch64__) || defined(_M_ARM64) +# define SIMDE_ARCH_AARCH64 1000 +#endif +#if defined(SIMDE_ARCH_AARCH64) +# define SIMDE_ARCH_AARCH64_CHECK(version) ((version) <= SIMDE_ARCH_AARCH64) +#else +# define SIMDE_ARCH_AARCH64_CHECK(version) (0) +#endif + +/* ARM SIMD ISA extensions */ +#if defined(__ARM_NEON) +# if defined(SIMDE_ARCH_AARCH64) +# define SIMDE_ARCH_ARM_NEON SIMDE_ARCH_AARCH64 +# elif defined(SIMDE_ARCH_ARM) +# define SIMDE_ARCH_ARM_NEON SIMDE_ARCH_ARM +# endif +#endif +#if defined(__ARM_FEATURE_SVE) +# define SIMDE_ARCH_ARM_SVE +#endif + +/* Blackfin + */ +#if defined(__bfin) || defined(__BFIN__) || defined(__bfin__) +# define SIMDE_ARCH_BLACKFIN 1 +#endif + +/* CRIS + */ +#if defined(__CRIS_arch_version) +# define SIMDE_ARCH_CRIS __CRIS_arch_version +#elif defined(__cris__) || defined(__cris) || defined(__CRIS) || defined(__CRIS__) +# define SIMDE_ARCH_CRIS 1 +#endif + +/* Convex + */ +#if defined(__convex_c38__) +# define SIMDE_ARCH_CONVEX 38 +#elif defined(__convex_c34__) +# define SIMDE_ARCH_CONVEX 34 +#elif defined(__convex_c32__) +# define SIMDE_ARCH_CONVEX 32 +#elif defined(__convex_c2__) +# define SIMDE_ARCH_CONVEX 2 +#elif defined(__convex__) +# define SIMDE_ARCH_CONVEX 1 +#endif +#if defined(SIMDE_ARCH_CONVEX) +# define SIMDE_ARCH_CONVEX_CHECK(version) ((version) <= SIMDE_ARCH_CONVEX) +#else +# define SIMDE_ARCH_CONVEX_CHECK(version) (0) +#endif + +/* Adapteva Epiphany + */ +#if defined(__epiphany__) +# define SIMDE_ARCH_EPIPHANY 1 +#endif + +/* Fujitsu FR-V + */ +#if defined(__frv__) +# define SIMDE_ARCH_FRV 1 +#endif + +/* H8/300 + */ +#if defined(__H8300__) +# define SIMDE_ARCH_H8300 +#endif + +/* Elbrus (8S, 8SV and successors) + */ +#if defined(__e2k__) +# define SIMDE_ARCH_E2K +#endif + +/* HP/PA / PA-RISC + */ +#if defined(__PA8000__) || defined(__HPPA20__) || defined(__RISC2_0__) || defined(_PA_RISC2_0) +# define SIMDE_ARCH_HPPA 20 +#elif defined(__PA7100__) || defined(__HPPA11__) || defined(_PA_RISC1_1) +# define SIMDE_ARCH_HPPA 11 +#elif defined(_PA_RISC1_0) +# define SIMDE_ARCH_HPPA 10 +#elif defined(__hppa__) || defined(__HPPA__) || defined(__hppa) +# define SIMDE_ARCH_HPPA 1 +#endif +#if defined(SIMDE_ARCH_HPPA) +# define SIMDE_ARCH_HPPA_CHECK(version) ((version) <= SIMDE_ARCH_HPPA) +#else +# define SIMDE_ARCH_HPPA_CHECK(version) (0) +#endif + +/* x86 + */ +#if defined(_M_IX86) +# define SIMDE_ARCH_X86 (_M_IX86 / 100) +#elif defined(__I86__) +# define SIMDE_ARCH_X86 __I86__ +#elif defined(i686) || defined(__i686) || defined(__i686__) +# define SIMDE_ARCH_X86 6 +#elif defined(i586) || defined(__i586) || defined(__i586__) +# define SIMDE_ARCH_X86 5 +#elif defined(i486) || defined(__i486) || defined(__i486__) +# define SIMDE_ARCH_X86 4 +#elif defined(i386) || defined(__i386) || defined(__i386__) +# define SIMDE_ARCH_X86 3 +#elif defined(_X86_) || defined(__X86__) || defined(__THW_INTEL__) +# define SIMDE_ARCH_X86 3 +#endif +#if defined(SIMDE_ARCH_X86) +# define SIMDE_ARCH_X86_CHECK(version) ((version) <= SIMDE_ARCH_X86) +#else +# define SIMDE_ARCH_X86_CHECK(version) (0) +#endif + +/* SIMD ISA extensions for x86/x86_64 and Elbrus */ +#if defined(SIMDE_ARCH_X86) || defined(SIMDE_ARCH_AMD64) || defined(SIMDE_ARCH_E2K) +# if defined(_M_IX86_FP) +# define SIMDE_ARCH_X86_MMX +# if (_M_IX86_FP >= 1) +# define SIMDE_ARCH_X86_SSE 1 +# endif +# if (_M_IX86_FP >= 2) +# define SIMDE_ARCH_X86_SSE2 1 +# endif +# elif defined(_M_X64) +# define SIMDE_ARCH_X86_SSE 1 +# define SIMDE_ARCH_X86_SSE2 1 +# else +# if defined(__MMX__) +# define SIMDE_ARCH_X86_MMX 1 +# endif +# if defined(__SSE__) +# define SIMDE_ARCH_X86_SSE 1 +# endif +# if defined(__SSE2__) +# define SIMDE_ARCH_X86_SSE2 1 +# endif +# endif +# if defined(__SSE3__) +# define SIMDE_ARCH_X86_SSE3 1 +# endif +# if defined(__SSSE3__) +# define SIMDE_ARCH_X86_SSSE3 1 +# endif +# if defined(__SSE4_1__) +# define SIMDE_ARCH_X86_SSE4_1 1 +# endif +# if defined(__SSE4_2__) +# define SIMDE_ARCH_X86_SSE4_2 1 +# endif +# if defined(__XOP__) +# define SIMDE_ARCH_X86_XOP 1 +# endif +# if defined(__AVX__) +# define SIMDE_ARCH_X86_AVX 1 +# if !defined(SIMDE_ARCH_X86_SSE3) +# define SIMDE_ARCH_X86_SSE3 1 +# endif +# if !defined(SIMDE_ARCH_X86_SSE4_1) +# define SIMDE_ARCH_X86_SSE4_1 1 +# endif +# if !defined(SIMDE_ARCH_X86_SSE4_1) +# define SIMDE_ARCH_X86_SSE4_2 1 +# endif +# endif +# if defined(__AVX2__) +# define SIMDE_ARCH_X86_AVX2 1 +# endif +# if defined(__FMA__) +# define SIMDE_ARCH_X86_FMA 1 +# if !defined(SIMDE_ARCH_X86_AVX) +# define SIMDE_ARCH_X86_AVX 1 +# endif +# endif +# if defined(__AVX512VP2INTERSECT__) +# define SIMDE_ARCH_X86_AVX512VP2INTERSECT 1 +# endif +# if defined(__AVX512VBMI__) +# define SIMDE_ARCH_X86_AVX512VBMI 1 +# endif +# if defined(__AVX512BW__) +# define SIMDE_ARCH_X86_AVX512BW 1 +# endif +# if defined(__AVX512CD__) +# define SIMDE_ARCH_X86_AVX512CD 1 +# endif +# if defined(__AVX512DQ__) +# define SIMDE_ARCH_X86_AVX512DQ 1 +# endif +# if defined(__AVX512F__) +# define SIMDE_ARCH_X86_AVX512F 1 +# endif +# if defined(__AVX512VL__) +# define SIMDE_ARCH_X86_AVX512VL 1 +# endif +# if defined(__GFNI__) +# define SIMDE_ARCH_X86_GFNI 1 +# endif +# if defined(__PCLMUL__) +# define SIMDE_ARCH_X86_PCLMUL 1 +# endif +# if defined(__VPCLMULQDQ__) +# define SIMDE_ARCH_X86_VPCLMULQDQ 1 +# endif +# if defined(__F16C__) +# define SIMDE_ARCH_X86_F16C 1 +# endif +#endif + +/* Itanium + */ +#if defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__ia64) || defined(_M_IA64) || defined(__itanium__) +# define SIMDE_ARCH_IA64 1 +#endif + +/* Renesas M32R + */ +#if defined(__m32r__) || defined(__M32R__) +# define SIMDE_ARCH_M32R +#endif + +/* Motorola 68000 + */ +#if defined(__mc68060__) || defined(__MC68060__) +# define SIMDE_ARCH_M68K 68060 +#elif defined(__mc68040__) || defined(__MC68040__) +# define SIMDE_ARCH_M68K 68040 +#elif defined(__mc68030__) || defined(__MC68030__) +# define SIMDE_ARCH_M68K 68030 +#elif defined(__mc68020__) || defined(__MC68020__) +# define SIMDE_ARCH_M68K 68020 +#elif defined(__mc68010__) || defined(__MC68010__) +# define SIMDE_ARCH_M68K 68010 +#elif defined(__mc68000__) || defined(__MC68000__) +# define SIMDE_ARCH_M68K 68000 +#endif +#if defined(SIMDE_ARCH_M68K) +# define SIMDE_ARCH_M68K_CHECK(version) ((version) <= SIMDE_ARCH_M68K) +#else +# define SIMDE_ARCH_M68K_CHECK(version) (0) +#endif + +/* Xilinx MicroBlaze + */ +#if defined(__MICROBLAZE__) || defined(__microblaze__) +# define SIMDE_ARCH_MICROBLAZE +#endif + +/* MIPS + */ +#if defined(_MIPS_ISA_MIPS64R2) +# define SIMDE_ARCH_MIPS 642 +#elif defined(_MIPS_ISA_MIPS64) +# define SIMDE_ARCH_MIPS 640 +#elif defined(_MIPS_ISA_MIPS32R2) +# define SIMDE_ARCH_MIPS 322 +#elif defined(_MIPS_ISA_MIPS32) +# define SIMDE_ARCH_MIPS 320 +#elif defined(_MIPS_ISA_MIPS4) +# define SIMDE_ARCH_MIPS 4 +#elif defined(_MIPS_ISA_MIPS3) +# define SIMDE_ARCH_MIPS 3 +#elif defined(_MIPS_ISA_MIPS2) +# define SIMDE_ARCH_MIPS 2 +#elif defined(_MIPS_ISA_MIPS1) +# define SIMDE_ARCH_MIPS 1 +#elif defined(_MIPS_ISA_MIPS) || defined(__mips) || defined(__MIPS__) +# define SIMDE_ARCH_MIPS 1 +#endif +#if defined(SIMDE_ARCH_MIPS) +# define SIMDE_ARCH_MIPS_CHECK(version) ((version) <= SIMDE_ARCH_MIPS) +#else +# define SIMDE_ARCH_MIPS_CHECK(version) (0) +#endif + +#if defined(__mips_loongson_mmi) +# define SIMDE_ARCH_MIPS_LOONGSON_MMI 1 +#endif + +/* Matsushita MN10300 + */ +#if defined(__MN10300__) || defined(__mn10300__) +# define SIMDE_ARCH_MN10300 1 +#endif + +/* POWER + */ +#if defined(_M_PPC) +# define SIMDE_ARCH_POWER _M_PPC +#elif defined(_ARCH_PWR9) +# define SIMDE_ARCH_POWER 900 +#elif defined(_ARCH_PWR8) +# define SIMDE_ARCH_POWER 800 +#elif defined(_ARCH_PWR7) +# define SIMDE_ARCH_POWER 700 +#elif defined(_ARCH_PWR6) +# define SIMDE_ARCH_POWER 600 +#elif defined(_ARCH_PWR5) +# define SIMDE_ARCH_POWER 500 +#elif defined(_ARCH_PWR4) +# define SIMDE_ARCH_POWER 400 +#elif defined(_ARCH_440) || defined(__ppc440__) +# define SIMDE_ARCH_POWER 440 +#elif defined(_ARCH_450) || defined(__ppc450__) +# define SIMDE_ARCH_POWER 450 +#elif defined(_ARCH_601) || defined(__ppc601__) +# define SIMDE_ARCH_POWER 601 +#elif defined(_ARCH_603) || defined(__ppc603__) +# define SIMDE_ARCH_POWER 603 +#elif defined(_ARCH_604) || defined(__ppc604__) +# define SIMDE_ARCH_POWER 604 +#elif defined(_ARCH_605) || defined(__ppc605__) +# define SIMDE_ARCH_POWER 605 +#elif defined(_ARCH_620) || defined(__ppc620__) +# define SIMDE_ARCH_POWER 620 +#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC) || defined(__ppc) +# define SIMDE_ARCH_POWER 1 +#endif +#if defined(SIMDE_ARCH_POWER) + #define SIMDE_ARCH_POWER_CHECK(version) ((version) <= SIMDE_ARCH_POWER) +#else + #define SIMDE_ARCH_POWER_CHECK(version) (0) +#endif + +#if defined(__ALTIVEC__) +# define SIMDE_ARCH_POWER_ALTIVEC SIMDE_ARCH_POWER +#endif +#if defined(SIMDE_ARCH_POWER) + #define SIMDE_ARCH_POWER_ALTIVEC_CHECK(version) ((version) <= SIMDE_ARCH_POWER) +#else + #define SIMDE_ARCH_POWER_ALTIVEC_CHECK(version) (0) +#endif + +/* SPARC + */ +#if defined(__sparc_v9__) || defined(__sparcv9) +# define SIMDE_ARCH_SPARC 9 +#elif defined(__sparc_v8__) || defined(__sparcv8) +# define SIMDE_ARCH_SPARC 8 +#elif defined(__sparc_v7__) || defined(__sparcv7) +# define SIMDE_ARCH_SPARC 7 +#elif defined(__sparc_v6__) || defined(__sparcv6) +# define SIMDE_ARCH_SPARC 6 +#elif defined(__sparc_v5__) || defined(__sparcv5) +# define SIMDE_ARCH_SPARC 5 +#elif defined(__sparc_v4__) || defined(__sparcv4) +# define SIMDE_ARCH_SPARC 4 +#elif defined(__sparc_v3__) || defined(__sparcv3) +# define SIMDE_ARCH_SPARC 3 +#elif defined(__sparc_v2__) || defined(__sparcv2) +# define SIMDE_ARCH_SPARC 2 +#elif defined(__sparc_v1__) || defined(__sparcv1) +# define SIMDE_ARCH_SPARC 1 +#elif defined(__sparc__) || defined(__sparc) +# define SIMDE_ARCH_SPARC 1 +#endif +#if defined(SIMDE_ARCH_SPARC) + #define SIMDE_ARCH_SPARC_CHECK(version) ((version) <= SIMDE_ARCH_SPARC) +#else + #define SIMDE_ARCH_SPARC_CHECK(version) (0) +#endif + +/* SuperH + */ +#if defined(__sh5__) || defined(__SH5__) +# define SIMDE_ARCH_SUPERH 5 +#elif defined(__sh4__) || defined(__SH4__) +# define SIMDE_ARCH_SUPERH 4 +#elif defined(__sh3__) || defined(__SH3__) +# define SIMDE_ARCH_SUPERH 3 +#elif defined(__sh2__) || defined(__SH2__) +# define SIMDE_ARCH_SUPERH 2 +#elif defined(__sh1__) || defined(__SH1__) +# define SIMDE_ARCH_SUPERH 1 +#elif defined(__sh__) || defined(__SH__) +# define SIMDE_ARCH_SUPERH 1 +#endif + +/* IBM System z + */ +#if defined(__370__) || defined(__THW_370__) || defined(__s390__) || defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH__) +# define SIMDE_ARCH_ZARCH __ARCH__ +#endif +#if defined(SIMDE_ARCH_ZARCH) + #define SIMDE_ARCH_ZARCH_CHECK(version) ((version) <= SIMDE_ARCH_ZARCH) +#else + #define SIMDE_ARCH_ZARCH_CHECK(version) (0) +#endif + +#if defined(SIMDE_ARCH_ZARCH) && defined(__VEC__) + #define SIMDE_ARCH_ZARCH_ZVECTOR SIMDE_ARCH_ZARCH +#endif + +/* TMS320 DSP + */ +#if defined(_TMS320C6740) || defined(__TMS320C6740__) +# define SIMDE_ARCH_TMS320 6740 +#elif defined(_TMS320C6700_PLUS) || defined(__TMS320C6700_PLUS__) +# define SIMDE_ARCH_TMS320 6701 +#elif defined(_TMS320C6700) || defined(__TMS320C6700__) +# define SIMDE_ARCH_TMS320 6700 +#elif defined(_TMS320C6600) || defined(__TMS320C6600__) +# define SIMDE_ARCH_TMS320 6600 +#elif defined(_TMS320C6400_PLUS) || defined(__TMS320C6400_PLUS__) +# define SIMDE_ARCH_TMS320 6401 +#elif defined(_TMS320C6400) || defined(__TMS320C6400__) +# define SIMDE_ARCH_TMS320 6400 +#elif defined(_TMS320C6200) || defined(__TMS320C6200__) +# define SIMDE_ARCH_TMS320 6200 +#elif defined(_TMS320C55X) || defined(__TMS320C55X__) +# define SIMDE_ARCH_TMS320 550 +#elif defined(_TMS320C54X) || defined(__TMS320C54X__) +# define SIMDE_ARCH_TMS320 540 +#elif defined(_TMS320C28X) || defined(__TMS320C28X__) +# define SIMDE_ARCH_TMS320 280 +#endif +#if defined(SIMDE_ARCH_TMS320) + #define SIMDE_ARCH_TMS320_CHECK(version) ((version) <= SIMDE_ARCH_TMS320) +#else + #define SIMDE_ARCH_TMS320_CHECK(version) (0) +#endif + +/* WebAssembly */ +#if defined(__wasm__) +# define SIMDE_ARCH_WASM 1 +#endif + +#if defined(SIMDE_ARCH_WASM) && defined(__wasm_simd128__) +# define SIMDE_ARCH_WASM_SIMD128 +#endif + +/* Xtensa + */ +#if defined(__xtensa__) || defined(__XTENSA__) +# define SIMDE_ARCH_XTENSA 1 +#endif + +#endif /* !defined(SIMDE_ARCH_H) */ +/* :: End ../simde/simde/simde-arch.h :: */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-features.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2020 Evan Nemerson + */ + +/* simde-arch.h is used to determine which features are available according + to the compiler. However, we want to make it possible to forcibly enable + or disable APIs */ + +#if !defined(SIMDE_FEATURES_H) +#define SIMDE_FEATURES_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-diagnostic.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +/* SIMDe targets a very wide range of standards and compilers, and our + * goal is to compile cleanly even with extremely aggressive warnings + * (i.e., -Weverything in clang, -Wextra in GCC, /W4 for MSVC, etc.) + * treated as errors. + * + * While our preference is to resolve the underlying issue a given + * diagnostic is warning us about, sometimes that's not possible. + * Fixing a warning in one compiler may cause problems in another. + * Sometimes a warning doesn't really apply to us (false positives), + * and sometimes adhering to a warning would mean dropping a feature + * we *know* the compiler supports since we have tested specifically + * for the compiler or feature. + * + * When practical, warnings are only disabled for specific code. For + * a list of warnings which are enabled by default in all SIMDe code, + * see SIMDE_DISABLE_UNWANTED_DIAGNOSTICS. Note that we restore the + * warning stack when SIMDe is done parsing, so code which includes + * SIMDe is not deprived of these warnings. + */ + +#if !defined(SIMDE_DIAGNOSTIC_H) +#define SIMDE_DIAGNOSTIC_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ + +/* This is only to help us implement functions like _mm_undefined_ps. */ +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + #undef SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ +#endif +#if HEDLEY_HAS_WARNING("-Wuninitialized") + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("clang diagnostic ignored \"-Wuninitialized\"") +#elif HEDLEY_GCC_VERSION_CHECK(4,2,0) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") +#elif HEDLEY_PGI_VERSION_CHECK(19,10,0) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("diag_suppress 549") +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("error_messages(off,SEC_UNINITIALIZED_MEM_READ,SEC_UNDEFINED_RETURN_VALUE,unassigned)") +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("error_messages(off,SEC_UNINITIALIZED_MEM_READ,SEC_UNDEFINED_RETURN_VALUE)") +#elif HEDLEY_SUNPRO_VERSION_CHECK(5,12,0) && defined(__cplusplus) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("error_messages(off,unassigned)") +#elif \ + HEDLEY_TI_VERSION_CHECK(16,9,9) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,2) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("diag_suppress 551") +#elif HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ _Pragma("warning(disable:592)") +#elif HEDLEY_MSVC_VERSION_CHECK(19,0,0) && !defined(__MSVC_RUNTIME_CHECKS) + #define SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ __pragma(warning(disable:4700)) +#endif + +/* GCC emits a lot of "notes" about the ABI being different for things + * in newer versions of GCC. We don't really care because all our + * functions are inlined and don't generate ABI. */ +#if HEDLEY_GCC_VERSION_CHECK(7,0,0) + #define SIMDE_DIAGNOSTIC_DISABLE_PSABI_ _Pragma("GCC diagnostic ignored \"-Wpsabi\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_PSABI_ +#endif + +/* Since MMX uses x87 FP registers, you're supposed to call _mm_empty() + * after each MMX function before any floating point instructions. + * Some compilers warn about functions which use MMX functions but + * don't call _mm_empty(). However, since SIMDe is implementyng the + * MMX API we shouldn't be calling _mm_empty(); we leave it to the + * caller to invoke simde_mm_empty(). */ +#if HEDLEY_INTEL_VERSION_CHECK(19,0,0) + #define SIMDE_DIAGNOSTIC_DISABLE_NO_EMMS_INSTRUCTION_ _Pragma("warning(disable:13200 13203)") +#elif defined(HEDLEY_MSVC_VERSION) + #define SIMDE_DIAGNOSTIC_DISABLE_NO_EMMS_INSTRUCTION_ __pragma(warning(disable:4799)) +#else + #define SIMDE_DIAGNOSTIC_DISABLE_NO_EMMS_INSTRUCTION_ +#endif + +/* Intel is pushing people to use OpenMP SIMD instead of Cilk+, so they + * emit a diagnostic if you use #pragma simd instead of + * #pragma omp simd. SIMDe supports OpenMP SIMD, you just need to + * compile with -qopenmp or -qopenmp-simd and define + * SIMDE_ENABLE_OPENMP. Cilk+ is just a fallback. */ +#if HEDLEY_INTEL_VERSION_CHECK(18,0,0) + #define SIMDE_DIAGNOSTIC_DISABLE_SIMD_PRAGMA_DEPRECATED_ _Pragma("warning(disable:3948)") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_SIMD_PRAGMA_DEPRECATED_ +#endif + +/* MSVC emits a diagnostic when we call a function (like + * simde_mm_set_epi32) while initializing a struct. We currently do + * this a *lot* in the tests. */ +#if \ + defined(HEDLEY_MSVC_VERSION) + #define SIMDE_DIAGNOSTIC_DISABLE_NON_CONSTANT_AGGREGATE_INITIALIZER_ __pragma(warning(disable:4204)) +#else + #define SIMDE_DIAGNOSTIC_DISABLE_NON_CONSTANT_AGGREGATE_INITIALIZER_ +#endif + +/* This warning needs a lot of work. It is triggered if all you do is + * pass the value to memcpy/__builtin_memcpy, or if you initialize a + * member of the union, even if that member takes up the entire union. + * Last tested with clang-10, hopefully things will improve in the + * future; if clang fixes this I'd love to enable it. */ +#if \ + HEDLEY_HAS_WARNING("-Wconditional-uninitialized") + #define SIMDE_DIAGNOSTIC_DISABLE_CONDITIONAL_UNINITIALIZED_ _Pragma("clang diagnostic ignored \"-Wconditional-uninitialized\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_CONDITIONAL_UNINITIALIZED_ +#endif + +/* This warning is meant to catch things like `0.3 + 0.4 == 0.7`, which + * will is false. However, SIMDe uses these operations exclusively + * for things like _mm_cmpeq_ps, for which we really do want to check + * for equality (or inequality). + * + * If someone wants to put together a SIMDE_FLOAT_EQUAL(a, op, b) macro + * which just wraps a check in some code do disable this diagnostic I'd + * be happy to accept it. */ +#if \ + HEDLEY_HAS_WARNING("-Wfloat-equal") || \ + HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL_ _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL_ +#endif + +/* This is because we use HEDLEY_STATIC_ASSERT for static assertions. + * If Hedley can't find an implementation it will preprocess to + * nothing, which means there will be a trailing semi-colon. */ +#if HEDLEY_HAS_WARNING("-Wextra-semi") + #define SIMDE_DIAGNOSTIC_DISABLE_EXTRA_SEMI_ _Pragma("clang diagnostic ignored \"-Wextra-semi\"") +#elif HEDLEY_GCC_VERSION_CHECK(8,1,0) && defined(__cplusplus) + #define SIMDE_DIAGNOSTIC_DISABLE_EXTRA_SEMI_ _Pragma("GCC diagnostic ignored \"-Wextra-semi\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_EXTRA_SEMI_ +#endif + +/* We do use a few variadic macros, which technically aren't available + * until C99 and C++11, but every compiler I'm aware of has supported + * them for much longer. That said, usage is isolated to the test + * suite and compilers known to support them. */ +#if HEDLEY_HAS_WARNING("-Wvariadic-macros") || HEDLEY_GCC_VERSION_CHECK(4,0,0) + #if HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") + #define SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_ \ + _Pragma("clang diagnostic ignored \"-Wvariadic-macros\"") \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") + #else + #define SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_ _Pragma("GCC diagnostic ignored \"-Wvariadic-macros\"") + #endif +#else + #define SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_ +#endif + +/* emscripten requires us to use a __wasm_unimplemented_simd128__ macro + * before we can access certain SIMD intrinsics, but this diagnostic + * warns about it being a reserved name. It is a reserved name, but + * it's reserved for the compiler and we are using it to convey + * information to the compiler. + * + * This is also used when enabling native aliases since we don't get to + * choose the macro names. */ +#if HEDLEY_HAS_WARNING("-Wdouble-promotion") + #define SIMDE_DIAGNOSTIC_DISABLE_RESERVED_ID_MACRO_ _Pragma("clang diagnostic ignored \"-Wreserved-id-macro\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_RESERVED_ID_MACRO_ +#endif + +/* clang 3.8 warns about the packed attribute being unnecessary when + * used in the _mm_loadu_* functions. That *may* be true for version + * 3.8, but for later versions it is crucial in order to make unaligned + * access safe. */ +#if HEDLEY_HAS_WARNING("-Wpacked") + #define SIMDE_DIAGNOSTIC_DISABLE_PACKED_ _Pragma("clang diagnostic ignored \"-Wpacked\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_PACKED_ +#endif + +/* Triggered when assigning a float to a double implicitly. We use + * explicit casts in SIMDe, this is only used in the test suite. */ +#if HEDLEY_HAS_WARNING("-Wdouble-promotion") + #define SIMDE_DIAGNOSTIC_DISABLE_DOUBLE_PROMOTION_ _Pragma("clang diagnostic ignored \"-Wdouble-promotion\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_DOUBLE_PROMOTION_ +#endif + +/* Several compilers treat conformant array parameters as VLAs. We + * test to make sure we're in C mode (C++ doesn't support CAPs), and + * that the version of the standard supports CAPs. We also reject + * some buggy compilers like MSVC (the logic is in Hedley if you want + * to take a look), but with certain warnings enabled some compilers + * still like to emit a diagnostic. */ +#if HEDLEY_HAS_WARNING("-Wvla") + #define SIMDE_DIAGNOSTIC_DISABLE_VLA_ _Pragma("clang diagnostic ignored \"-Wvla\"") +#elif HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define SIMDE_DIAGNOSTIC_DISABLE_VLA_ _Pragma("GCC diagnostic ignored \"-Wvla\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_VLA_ +#endif + +#if HEDLEY_HAS_WARNING("-Wused-but-marked-unused") + #define SIMDE_DIAGNOSTIC_DISABLE_USED_BUT_MARKED_UNUSED_ _Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_USED_BUT_MARKED_UNUSED_ +#endif + +#if HEDLEY_HAS_WARNING("-Wpass-failed") + #define SIMDE_DIAGNOSTIC_DISABLE_PASS_FAILED_ _Pragma("clang diagnostic ignored \"-Wpass-failed\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_PASS_FAILED_ +#endif + +#if HEDLEY_HAS_WARNING("-Wpadded") + #define SIMDE_DIAGNOSTIC_DISABLE_PADDED_ _Pragma("clang diagnostic ignored \"-Wpadded\"") +#elif HEDLEY_MSVC_VERSION_CHECK(19,0,0) /* Likely goes back further */ + #define SIMDE_DIAGNOSTIC_DISABLE_PADDED_ __pragma(warning(disable:4324)) +#else + #define SIMDE_DIAGNOSTIC_DISABLE_PADDED_ +#endif + +#if HEDLEY_HAS_WARNING("-Wzero-as-null-pointer-constant") + #define SIMDE_DIAGNOSTIC_DISABLE_ZERO_AS_NULL_POINTER_CONSTANT_ _Pragma("clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_ZERO_AS_NULL_POINTER_CONSTANT_ +#endif + +#if HEDLEY_HAS_WARNING("-Wold-style-cast") + #define SIMDE_DIAGNOSTIC_DISABLE_OLD_STYLE_CAST_ _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_OLD_STYLE_CAST_ +#endif + +#if HEDLEY_HAS_WARNING("-Wcast-function-type") || HEDLEY_GCC_VERSION_CHECK(8,0,0) + #define SIMDE_DIAGNOSTIC_DISABLE_CAST_FUNCTION_TYPE_ _Pragma("GCC diagnostic ignored \"-Wcast-function-type\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_CAST_FUNCTION_TYPE_ +#endif + +/* clang will emit this warning when we use C99 extensions whan not in + * C99 mode, even though it does support this. In such cases we check + * the compiler and version first, so we know it's not a problem. */ +#if HEDLEY_HAS_WARNING("-Wc99-extensions") + #define SIMDE_DIAGNOSTIC_DISABLE_C99_EXTENSIONS_ _Pragma("clang diagnostic ignored \"-Wc99-extensions\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_C99_EXTENSIONS_ +#endif + +/* https://github.com/simd-everywhere/simde/issues/277 */ +#if defined(HEDLEY_GCC_VERSION) && HEDLEY_GCC_VERSION_CHECK(4,6,0) && !HEDLEY_GCC_VERSION_CHECK(6,4,0) && defined(__cplusplus) + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_UNUSED_BUT_SET_VARIBALE_ _Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_UNUSED_BUT_SET_VARIBALE_ +#endif + +/* This is the warning that you normally define _CRT_SECURE_NO_WARNINGS + * to silence, but you have to do that before including anything and + * that would require reordering includes. */ +#if defined(_MSC_VER) + #define SIMDE_DIAGNOSTIC_DISABLE_ANNEX_K_ __pragma(warning(disable:4996)) +#else + #define SIMDE_DIAGNOSTIC_DISABLE_ANNEX_K_ +#endif + +/* Some compilers, such as clang, may use `long long` for 64-bit + * integers, but `long long` triggers a diagnostic with + * -Wc++98-compat-pedantic which says 'long long' is incompatible with + * C++98. */ +#if HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") + #if HEDLEY_HAS_WARNING("-Wc++11-long-long") + #define SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_ \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ + _Pragma("clang diagnostic ignored \"-Wc++11-long-long\"") + #else + #define SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_ _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") + #endif +#else + #define SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_ +#endif + +/* Some problem as above */ +#if HEDLEY_HAS_WARNING("-Wc++11-long-long") + #define SIMDE_DIAGNOSTIC_DISABLE_CPP11_LONG_LONG_ _Pragma("clang diagnostic ignored \"-Wc++11-long-long\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_CPP11_LONG_LONG_ +#endif + +/* emscripten emits this whenever stdin/stdout/stderr is used in a + * macro. */ +#if HEDLEY_HAS_WARNING("-Wdisabled-macro-expansion") + #define SIMDE_DIAGNOSTIC_DISABLE_DISABLED_MACRO_EXPANSION_ _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_DISABLED_MACRO_EXPANSION_ +#endif + +/* Clang uses C11 generic selections to implement some AltiVec + * functions, which triggers this diagnostic when not compiling + * in C11 mode */ +#if HEDLEY_HAS_WARNING("-Wc11-extensions") + #define SIMDE_DIAGNOSTIC_DISABLE_C11_EXTENSIONS_ _Pragma("clang diagnostic ignored \"-Wc11-extensions\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_C11_EXTENSIONS_ +#endif + +/* Clang sometimes triggers this warning in macros in the AltiVec and + * NEON headers, or due to missing functions. */ +#if HEDLEY_HAS_WARNING("-Wvector-conversion") + #define SIMDE_DIAGNOSTIC_DISABLE_VECTOR_CONVERSION_ _Pragma("clang diagnostic ignored \"-Wvector-conversion\"") + /* For NEON, the situation with -Wvector-conversion in clang < 10 is + * bad enough that we just disable the warning altogether. On x86, + * clang has similar issues on several sse4.2+ intrinsics before 3.8. */ + #if \ + (defined(SIMDE_ARCH_ARM) && SIMDE_DETECT_CLANG_VERSION_NOT(10,0,0)) || \ + SIMDE_DETECT_CLANG_VERSION_NOT(3,8,0) + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_VECTOR_CONVERSION_ SIMDE_DIAGNOSTIC_DISABLE_VECTOR_CONVERSION_ + #endif +#else + #define SIMDE_DIAGNOSTIC_DISABLE_VECTOR_CONVERSION_ +#endif +#if !defined(SIMDE_DIAGNOSTIC_DISABLE_BUGGY_VECTOR_CONVERSION_) + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_VECTOR_CONVERSION_ +#endif + +/* Prior to 5.0, clang didn't support disabling diagnostics in + * statement exprs. As a result, some macros we use don't + * properly silence warnings. */ +#if SIMDE_DETECT_CLANG_VERSION_NOT(5,0,0) && HEDLEY_HAS_WARNING("-Wcast-qual") && HEDLEY_HAS_WARNING("-Wcast-align") + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_CASTS_ _Pragma("clang diagnostic ignored \"-Wcast-qual\"") _Pragma("clang diagnostic ignored \"-Wcast-align\"") +#elif SIMDE_DETECT_CLANG_VERSION_NOT(5,0,0) && HEDLEY_HAS_WARNING("-Wcast-qual") + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_CASTS_ _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif SIMDE_DETECT_CLANG_VERSION_NOT(5,0,0) && HEDLEY_HAS_WARNING("-Wcast-align") + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_CASTS_ _Pragma("clang diagnostic ignored \"-Wcast-align\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_BUGGY_CASTS_ +#endif + +/* SLEEF triggers this a *lot* in their headers */ +#if HEDLEY_HAS_WARNING("-Wignored-qualifiers") + #define SIMDE_DIAGNOSTIC_DISABLE_IGNORED_QUALIFIERS_ _Pragma("clang diagnostic ignored \"-Wignored-qualifiers\"") +#elif HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define SIMDE_DIAGNOSTIC_DISABLE_IGNORED_QUALIFIERS_ _Pragma("GCC diagnostic ignored \"-Wignored-qualifiers\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_IGNORED_QUALIFIERS_ +#endif + +/* GCC emits this under some circumstances when using __int128 */ +#if HEDLEY_GCC_VERSION_CHECK(4,8,0) + #define SIMDE_DIAGNOSTIC_DISABLE_PEDANTIC_ _Pragma("GCC diagnostic ignored \"-Wpedantic\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_PEDANTIC_ +#endif + +/* MSVC doesn't like (__assume(0), code) and will warn about code being + * unreachable, but we want it there because not all compilers + * understand the unreachable macro and will complain if it is missing. + * I'm planning on adding a new macro to Hedley to handle this a bit + * more elegantly, but until then... */ +#if defined(HEDLEY_MSVC_VERSION) + #define SIMDE_DIAGNOSTIC_DISABLE_UNREACHABLE_ __pragma(warning(disable:4702)) +#else + #define SIMDE_DIAGNOSTIC_DISABLE_UNREACHABLE_ +#endif + +/* This is a false positive from GCC in a few places. */ +#if HEDLEY_GCC_VERSION_CHECK(4,7,0) + #define SIMDE_DIAGNOSTIC_DISABLE_MAYBE_UNINITIAZILED_ _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +#else + #define SIMDE_DIAGNOSTIC_DISABLE_MAYBE_UNINITIAZILED_ +#endif + +#if defined(SIMDE_ENABLE_NATIVE_ALIASES) + #define SIMDE_DISABLE_UNWANTED_DIAGNOSTICS_NATIVE_ALIASES_ \ + SIMDE_DIAGNOSTIC_DISABLE_RESERVED_ID_MACRO_ +#else + #define SIMDE_DISABLE_UNWANTED_DIAGNOSTICS_NATIVE_ALIASES_ +#endif + +#define SIMDE_DISABLE_UNWANTED_DIAGNOSTICS \ + HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION \ + SIMDE_DISABLE_UNWANTED_DIAGNOSTICS_NATIVE_ALIASES_ \ + SIMDE_DIAGNOSTIC_DISABLE_PSABI_ \ + SIMDE_DIAGNOSTIC_DISABLE_NO_EMMS_INSTRUCTION_ \ + SIMDE_DIAGNOSTIC_DISABLE_SIMD_PRAGMA_DEPRECATED_ \ + SIMDE_DIAGNOSTIC_DISABLE_CONDITIONAL_UNINITIALIZED_ \ + SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL_ \ + SIMDE_DIAGNOSTIC_DISABLE_NON_CONSTANT_AGGREGATE_INITIALIZER_ \ + SIMDE_DIAGNOSTIC_DISABLE_EXTRA_SEMI_ \ + SIMDE_DIAGNOSTIC_DISABLE_VLA_ \ + SIMDE_DIAGNOSTIC_DISABLE_USED_BUT_MARKED_UNUSED_ \ + SIMDE_DIAGNOSTIC_DISABLE_PASS_FAILED_ \ + SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_ \ + SIMDE_DIAGNOSTIC_DISABLE_CPP11_LONG_LONG_ \ + SIMDE_DIAGNOSTIC_DISABLE_BUGGY_UNUSED_BUT_SET_VARIBALE_ \ + SIMDE_DIAGNOSTIC_DISABLE_BUGGY_CASTS_ \ + SIMDE_DIAGNOSTIC_DISABLE_BUGGY_VECTOR_CONVERSION_ + +#endif /* !defined(SIMDE_DIAGNOSTIC_H) */ +/* :: End ../simde/simde/simde-diagnostic.h :: */ + +#if !defined(SIMDE_X86_SVML_NATIVE) && !defined(SIMDE_X86_SVML_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SVML) + #define SIMDE_X86_SVML_NATIVE + #endif +#endif +#if defined(SIMDE_X86_SVML_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512VP2INTERSECT_NATIVE) && !defined(SIMDE_X86_AVX512VP2INTERSECT_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512VP2INTERSECT) + #define SIMDE_X86_AVX512VP2INTERSECT_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512VP2INTERSECT_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512VBMI_NATIVE) && !defined(SIMDE_X86_AVX512VBMI_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512VBMI) + #define SIMDE_X86_AVX512VBMI_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512VBMI_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512CD_NATIVE) && !defined(SIMDE_X86_AVX512CD_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512CD) + #define SIMDE_X86_AVX512CD_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512CD_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512DQ_NATIVE) && !defined(SIMDE_X86_AVX512DQ_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512DQ) + #define SIMDE_X86_AVX512DQ_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512DQ_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_X86_AVX512VL_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512VL) + #define SIMDE_X86_AVX512VL_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_X86_AVX512BW_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512BW) + #define SIMDE_X86_AVX512BW_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX512F_NATIVE) && !defined(SIMDE_X86_AVX512F_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX512F) + #define SIMDE_X86_AVX512F_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX512F_NATIVE) && !defined(SIMDE_X86_AVX2_NATIVE) + #define SIMDE_X86_AVX2_NATIVE +#endif + +#if !defined(SIMDE_X86_FMA_NATIVE) && !defined(SIMDE_X86_FMA_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_FMA) + #define SIMDE_X86_FMA_NATIVE + #endif +#endif +#if defined(SIMDE_X86_FMA_NATIVE) && !defined(SIMDE_X86_AVX_NATIVE) + #define SIMDE_X86_AVX_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX2_NATIVE) && !defined(SIMDE_X86_AVX2_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX2) + #define SIMDE_X86_AVX2_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX2_NATIVE) && !defined(SIMDE_X86_AVX_NATIVE) + #define SIMDE_X86_AVX_NATIVE +#endif + +#if !defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_X86_AVX_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_AVX) + #define SIMDE_X86_AVX_NATIVE + #endif +#endif +#if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_X86_SSE4_1_NATIVE) + #define SIMDE_X86_SSE4_2_NATIVE +#endif + +#if !defined(SIMDE_X86_XOP_NATIVE) && !defined(SIMDE_X86_XOP_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_XOP) + #define SIMDE_X86_XOP_NATIVE + #endif +#endif +#if defined(SIMDE_X86_XOP_NATIVE) && !defined(SIMDE_X86_SSE4_2_NATIVE) + #define SIMDE_X86_SSE4_2_NATIVE +#endif + +#if !defined(SIMDE_X86_SSE4_2_NATIVE) && !defined(SIMDE_X86_SSE4_2_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SSE4_2) + #define SIMDE_X86_SSE4_2_NATIVE + #endif +#endif +#if defined(SIMDE_X86_SSE4_2_NATIVE) && !defined(SIMDE_X86_SSE4_1_NATIVE) + #define SIMDE_X86_SSE4_1_NATIVE +#endif + +#if !defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(SIMDE_X86_SSE4_1_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SSE4_1) + #define SIMDE_X86_SSE4_1_NATIVE + #endif +#endif +#if defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(SIMDE_X86_SSSE3_NATIVE) + #define SIMDE_X86_SSSE3_NATIVE +#endif + +#if !defined(SIMDE_X86_SSSE3_NATIVE) && !defined(SIMDE_X86_SSSE3_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SSSE3) + #define SIMDE_X86_SSSE3_NATIVE + #endif +#endif +#if defined(SIMDE_X86_SSSE3_NATIVE) && !defined(SIMDE_X86_SSE3_NATIVE) + #define SIMDE_X86_SSE3_NATIVE +#endif + +#if !defined(SIMDE_X86_SSE3_NATIVE) && !defined(SIMDE_X86_SSE3_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SSE3) + #define SIMDE_X86_SSE3_NATIVE + #endif +#endif +#if defined(SIMDE_X86_SSE3_NATIVE) && !defined(SIMDE_X86_SSE2_NATIVE) + #define SIMDE_X86_SSE2_NATIVE +#endif + +#if !defined(SIMDE_X86_SSE2_NATIVE) && !defined(SIMDE_X86_SSE2_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SSE2) + #define SIMDE_X86_SSE2_NATIVE + #endif +#endif +#if defined(SIMDE_X86_SSE2_NATIVE) && !defined(SIMDE_X86_SSE_NATIVE) + #define SIMDE_X86_SSE_NATIVE +#endif + +#if !defined(SIMDE_X86_SSE_NATIVE) && !defined(SIMDE_X86_SSE_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_SSE) + #define SIMDE_X86_SSE_NATIVE + #endif +#endif + +#if !defined(SIMDE_X86_MMX_NATIVE) && !defined(SIMDE_X86_MMX_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_MMX) + #define SIMDE_X86_MMX_NATIVE + #endif +#endif + +#if !defined(SIMDE_X86_GFNI_NATIVE) && !defined(SIMDE_X86_GFNI_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_GFNI) + #define SIMDE_X86_GFNI_NATIVE + #endif +#endif + +#if !defined(SIMDE_X86_PCLMUL_NATIVE) && !defined(SIMDE_X86_PCLMUL_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_PCLMUL) + #define SIMDE_X86_PCLMUL_NATIVE + #endif +#endif + +#if !defined(SIMDE_X86_VPCLMULQDQ_NATIVE) && !defined(SIMDE_X86_VPCLMULQDQ_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_VPCLMULQDQ) + #define SIMDE_X86_VPCLMULQDQ_NATIVE + #endif +#endif + +#if !defined(SIMDE_X86_F16C_NATIVE) && !defined(SIMDE_X86_F16C_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_X86_F16C) + #define SIMDE_X86_F16C_NATIVE + #endif +#endif + +#if !defined(SIMDE_X86_SVML_NATIVE) && !defined(SIMDE_X86_SVML_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(__INTEL_COMPILER) + #define SIMDE_X86_SVML_NATIVE + #endif +#endif + +#if defined(HEDLEY_MSVC_VERSION) + #pragma warning(push) + #pragma warning(disable:4799) +#endif + +#if \ + defined(SIMDE_X86_AVX_NATIVE) || defined(SIMDE_X86_GFNI_NATIVE) + #include +#elif defined(SIMDE_X86_SSE4_2_NATIVE) + #include +#elif defined(SIMDE_X86_SSE4_1_NATIVE) + #include +#elif defined(SIMDE_X86_SSSE3_NATIVE) + #include +#elif defined(SIMDE_X86_SSE3_NATIVE) + #include +#elif defined(SIMDE_X86_SSE2_NATIVE) + #include +#elif defined(SIMDE_X86_SSE_NATIVE) + #include +#elif defined(SIMDE_X86_MMX_NATIVE) + #include +#endif + +#if defined(SIMDE_X86_XOP_NATIVE) + #if defined(_MSC_VER) + #include + #else + #include + #endif +#endif + +#if defined(HEDLEY_MSVC_VERSION) + #pragma warning(pop) +#endif + +#if !defined(SIMDE_ARM_NEON_A64V8_NATIVE) && !defined(SIMDE_ARM_NEON_A64V8_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_ARM_NEON) && defined(SIMDE_ARCH_AARCH64) && SIMDE_ARCH_ARM_CHECK(80) + #define SIMDE_ARM_NEON_A64V8_NATIVE + #endif +#endif +#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) && !defined(SIMDE_ARM_NEON_A32V8_NATIVE) + #define SIMDE_ARM_NEON_A32V8_NATIVE +#endif + +#if !defined(SIMDE_ARM_NEON_A32V8_NATIVE) && !defined(SIMDE_ARM_NEON_A32V8_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_ARM_NEON) && SIMDE_ARCH_ARM_CHECK(80) && (__ARM_NEON_FP & 0x02) + #define SIMDE_ARM_NEON_A32V8_NATIVE + #endif +#endif +#if defined(SIMDE_ARM_NEON_A32V8_NATIVE) && !defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define SIMDE_ARM_NEON_A32V7_NATIVE +#endif + +#if !defined(SIMDE_ARM_NEON_A32V7_NATIVE) && !defined(SIMDE_ARM_NEON_A32V7_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_ARM_NEON) && SIMDE_ARCH_ARM_CHECK(70) + #define SIMDE_ARM_NEON_A32V7_NATIVE + #endif +#endif +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #include +#endif + +#if !defined(SIMDE_ARM_SVE_NATIVE) && !defined(SIMDE_ARM_SVE_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_ARM_SVE) + #define SIMDE_ARM_SVE_NATIVE + #include + #endif +#endif + +#if !defined(SIMDE_WASM_SIMD128_NATIVE) && !defined(SIMDE_WASM_SIMD128_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_WASM_SIMD128) + #define SIMDE_WASM_SIMD128_NATIVE + #endif +#endif +#if defined(SIMDE_WASM_SIMD128_NATIVE) + #include +#endif + +#if !defined(SIMDE_POWER_ALTIVEC_P9_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P9_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_POWER_ALTIVEC_CHECK(900) + #define SIMDE_POWER_ALTIVEC_P9_NATIVE + #endif +#endif +#if defined(SIMDE_POWER_ALTIVEC_P9_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P8) + #define SIMDE_POWER_ALTIVEC_P8_NATIVE +#endif + +#if !defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P8_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_POWER_ALTIVEC_CHECK(800) + #define SIMDE_POWER_ALTIVEC_P8_NATIVE + #endif +#endif +#if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P7) + #define SIMDE_POWER_ALTIVEC_P7_NATIVE +#endif + +#if !defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P7_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_POWER_ALTIVEC_CHECK(700) + #define SIMDE_POWER_ALTIVEC_P7_NATIVE + #endif +#endif +#if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P6) + #define SIMDE_POWER_ALTIVEC_P6_NATIVE +#endif + +#if !defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P6_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_POWER_ALTIVEC_CHECK(600) + #define SIMDE_POWER_ALTIVEC_P6_NATIVE + #endif +#endif +#if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P5) + #define SIMDE_POWER_ALTIVEC_P5_NATIVE +#endif + +#if !defined(SIMDE_POWER_ALTIVEC_P5_NATIVE) && !defined(SIMDE_POWER_ALTIVEC_P5_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_POWER_ALTIVEC_CHECK(500) + #define SIMDE_POWER_ALTIVEC_P5_NATIVE + #endif +#endif + +#if !defined(SIMDE_ZARCH_ZVECTOR_15_NATIVE) && !defined(SIMDE_ZARCH_ZVECTOR_15_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_ZARCH_CHECK(13) && defined(SIMDE_ARCH_ZARCH_ZVECTOR) + #define SIMDE_ZARCH_ZVECTOR_15_NATIVE + #endif +#endif + +#if !defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) && !defined(SIMDE_ZARCH_ZVECTOR_14_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_ZARCH_CHECK(12) && defined(SIMDE_ARCH_ZARCH_ZVECTOR) + #define SIMDE_ZARCH_ZVECTOR_14_NATIVE + #endif +#endif + +#if !defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) && !defined(SIMDE_ZARCH_ZVECTOR_13_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if SIMDE_ARCH_ZARCH_CHECK(11) && defined(SIMDE_ARCH_ZARCH_ZVECTOR) + #define SIMDE_ZARCH_ZVECTOR_13_NATIVE + #endif +#endif + +#if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + /* AltiVec conflicts with lots of stuff. The bool keyword conflicts + * with the bool keyword in C++ and the bool macro in C99+ (defined + * in stdbool.h). The vector keyword conflicts with std::vector in + * C++ if you are `using std;`. + * + * Luckily AltiVec allows you to use `__vector`/`__bool`/`__pixel` + * instead, but altivec.h will unconditionally define + * `vector`/`bool`/`pixel` so we need to work around that. + * + * Unfortunately this means that if your code uses AltiVec directly + * it may break. If this is the case you'll want to define + * `SIMDE_POWER_ALTIVEC_NO_UNDEF` before including SIMDe. Or, even + * better, port your code to use the double-underscore versions. */ + #if defined(bool) + #undef bool + #endif + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + #include + + #if !defined(SIMDE_POWER_ALTIVEC_NO_UNDEF) + #if defined(vector) + #undef vector + #endif + #if defined(pixel) + #undef pixel + #endif + #if defined(bool) + #undef bool + #endif + #endif /* !defined(SIMDE_POWER_ALTIVEC_NO_UNDEF) */ + #elif defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + #include + #endif + + /* Use these intsead of vector/pixel/bool in SIMDe. */ + #define SIMDE_POWER_ALTIVEC_VECTOR(T) __vector T + #define SIMDE_POWER_ALTIVEC_PIXEL __pixel + #define SIMDE_POWER_ALTIVEC_BOOL __bool + + /* Re-define bool if we're using stdbool.h */ + #if !defined(__cplusplus) && defined(__bool_true_false_are_defined) && !defined(SIMDE_POWER_ALTIVEC_NO_UNDEF) + #define bool _Bool + #endif +#endif + +#if !defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) && !defined(SIMDE_MIPS_LOONGSON_MMI_NO_NATIVE) && !defined(SIMDE_NO_NATIVE) + #if defined(SIMDE_ARCH_MIPS_LOONGSON_MMI) + #define SIMDE_MIPS_LOONGSON_MMI_NATIVE 1 + #endif +#endif +#if defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + #include +#endif + +/* This is used to determine whether or not to fall back on a vector + * function in an earlier ISA extensions, as well as whether + * we expected any attempts at vectorization to be fruitful or if we + * expect to always be running serial code. */ + +#if !defined(SIMDE_NATURAL_VECTOR_SIZE) + #if defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_NATURAL_VECTOR_SIZE (512) + #elif defined(SIMDE_X86_AVX_NATIVE) + #define SIMDE_NATURAL_VECTOR_SIZE (256) + #elif \ + defined(SIMDE_X86_SSE_NATIVE) || \ + defined(SIMDE_ARM_NEON_A32V7_NATIVE) || \ + defined(SIMDE_WASM_SIMD128_NATIVE) || \ + defined(SIMDE_POWER_ALTIVEC_P5_NATIVE) + #define SIMDE_NATURAL_VECTOR_SIZE (128) + #endif + + #if !defined(SIMDE_NATURAL_VECTOR_SIZE) + #define SIMDE_NATURAL_VECTOR_SIZE (0) + #endif +#endif + +#define SIMDE_NATURAL_VECTOR_SIZE_LE(x) ((SIMDE_NATURAL_VECTOR_SIZE > 0) && (SIMDE_NATURAL_VECTOR_SIZE <= (x))) +#define SIMDE_NATURAL_VECTOR_SIZE_GE(x) ((SIMDE_NATURAL_VECTOR_SIZE > 0) && (SIMDE_NATURAL_VECTOR_SIZE >= (x))) + +/* Native aliases */ +#if defined(SIMDE_ENABLE_NATIVE_ALIASES) + #if !defined(SIMDE_X86_MMX_NATIVE) + #define SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_SSE_NATIVE) + #define SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_SSE2_NATIVE) + #define SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_SSE3_NATIVE) + #define SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_SSSE3_NATIVE) + #define SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_SSE4_1_NATIVE) + #define SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_SSE4_2_NATIVE) + #define SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX_NATIVE) + #define SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX2_NATIVE) + #define SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_FMA_NATIVE) + #define SIMDE_X86_FMA_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX512F_NATIVE) + #define SIMDE_X86_AVX512F_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX512VL_NATIVE) + #define SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX512BW_NATIVE) + #define SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX512DQ_NATIVE) + #define SIMDE_X86_AVX512DQ_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_AVX512CD_NATIVE) + #define SIMDE_X86_AVX512CD_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_GFNI_NATIVE) + #define SIMDE_X86_GFNI_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_PCLMUL_NATIVE) + #define SIMDE_X86_PCLMUL_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_VPCLMULQDQ_NATIVE) + #define SIMDE_X86_VPCLMULQDQ_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_X86_F16C_NATIVE) + #define SIMDE_X86_F16C_ENABLE_NATIVE_ALIASES + #endif + + #if !defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define SIMDE_ARM_NEON_A32V7_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_ARM_NEON_A32V8_NATIVE) + #define SIMDE_ARM_NEON_A32V8_ENABLE_NATIVE_ALIASES + #endif + #if !defined(SIMDE_ARM_NEON_A64V8_NATIVE) + #define SIMDE_ARM_NEON_A64V8_ENABLE_NATIVE_ALIASES + #endif + + #if !defined(SIMDE_WASM_SIMD128_NATIVE) + #define SIMDE_WASM_SIMD128_ENABLE_NATIVE_ALIASES + #endif +#endif + +/* Are floating point values stored using IEEE 754? Knowing + * this at during preprocessing is a bit tricky, mostly because what + * we're curious about is how values are stored and not whether the + * implementation is fully conformant in terms of rounding, NaN + * handling, etc. + * + * For example, if you use -ffast-math or -Ofast on + * GCC or clang IEEE 754 isn't strictly followed, therefore IEE 754 + * support is not advertised (by defining __STDC_IEC_559__). + * + * However, what we care about is whether it is safe to assume that + * floating point values are stored in IEEE 754 format, in which case + * we can provide faster implementations of some functions. + * + * Luckily every vaugely modern architecture I'm aware of uses IEEE 754- + * so we just assume IEEE 754 for now. There is a test which verifies + * this, if that test fails sowewhere please let us know and we'll add + * an exception for that platform. Meanwhile, you can define + * SIMDE_NO_IEEE754_STORAGE. */ +#if !defined(SIMDE_IEEE754_STORAGE) && !defined(SIMDE_NO_IEE754_STORAGE) + #define SIMDE_IEEE754_STORAGE +#endif + +#endif /* !defined(SIMDE_FEATURES_H) */ +/* :: End ../simde/simde/simde-features.h :: */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-math.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +/* Attempt to find math functions. Functions may be in , + * , compiler built-ins/intrinsics, or platform/architecture + * specific headers. In some cases, especially those not built in to + * libm, we may need to define our own implementations. */ + +#if !defined(SIMDE_MATH_H) +#define SIMDE_MATH_H 1 + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ + +#include +#if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + #include +#endif + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS + +/* SLEEF support + * https://sleef.org/ + * + * If you include prior to including SIMDe, SIMDe will use + * SLEEF. You can also define SIMDE_MATH_SLEEF_ENABLE prior to + * including SIMDe to force the issue. + * + * Note that SLEEF does requires linking to libsleef. + * + * By default, SIMDe will use the 1 ULP functions, but if you use + * SIMDE_ACCURACY_PREFERENCE of 0 we will use up to 4 ULP. This is + * only the case for the simde_math_* functions; for code in other + * SIMDe headers which calls SLEEF directly we may use functions with + * greater error if the API we're implementing is less precise (for + * example, SVML guarantees 4 ULP, so we will generally use the 3.5 + * ULP functions from SLEEF). */ +#if !defined(SIMDE_MATH_SLEEF_DISABLE) + #if defined(__SLEEF_H__) + #define SIMDE_MATH_SLEEF_ENABLE + #endif +#endif + +#if defined(SIMDE_MATH_SLEEF_ENABLE) && !defined(__SLEEF_H__) + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_IGNORED_QUALIFIERS_ + #include + HEDLEY_DIAGNOSTIC_POP +#endif + +#if defined(SIMDE_MATH_SLEEF_ENABLE) && defined(__SLEEF_H__) + #if defined(SLEEF_VERSION_MAJOR) + #define SIMDE_MATH_SLEEF_VERSION_CHECK(major, minor, patch) (HEDLEY_VERSION_ENCODE(SLEEF_VERSION_MAJOR, SLEEF_VERSION_MINOR, SLEEF_VERSION_PATCHLEVEL) >= HEDLEY_VERSION_ENCODE(major, minor, patch)) + #else + #define SIMDE_MATH_SLEEF_VERSION_CHECK(major, minor, patch) (HEDLEY_VERSION_ENCODE(3,0,0) >= HEDLEY_VERSION_ENCODE(major, minor, patch)) + #endif +#else + #define SIMDE_MATH_SLEEF_VERSION_CHECK(major, minor, patch) (0) +#endif + +#if defined(__has_builtin) + #define SIMDE_MATH_BUILTIN_LIBM(func) __has_builtin(__builtin_##func) +#elif \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_GCC_VERSION_CHECK(4,4,0) + #define SIMDE_MATH_BUILTIN_LIBM(func) (1) +#else + #define SIMDE_MATH_BUILTIN_LIBM(func) (0) +#endif + +#if defined(HUGE_VAL) + /* Looks like or has already been included. */ + + /* The math.h from libc++ (yes, the C header from the C++ standard + * library) will define an isnan function, but not an isnan macro + * like the C standard requires. So we detect the header guards + * macro libc++ uses. */ + #if defined(isnan) || (defined(_LIBCPP_MATH_H) && !defined(_LIBCPP_CMATH)) + #define SIMDE_MATH_HAVE_MATH_H + #elif defined(__cplusplus) + #define SIMDE_MATH_HAVE_CMATH + #endif +#elif defined(__has_include) + #if defined(__cplusplus) && (__cplusplus >= 201103L) && __has_include() + #define SIMDE_MATH_HAVE_CMATH + #include + #elif __has_include() + #define SIMDE_MATH_HAVE_MATH_H + #include + #elif !defined(SIMDE_MATH_NO_LIBM) + #define SIMDE_MATH_NO_LIBM + #endif +#elif !defined(SIMDE_MATH_NO_LIBM) + #if defined(__cplusplus) && (__cplusplus >= 201103L) + #define SIMDE_MATH_HAVE_CMATH + HEDLEY_DIAGNOSTIC_PUSH + #if defined(HEDLEY_MSVC_VERSION) + /* VS 14 emits this diagnostic about noexcept being used on a + * function, which we can't do anything about. */ + #pragma warning(disable:4996) + #endif + #include + HEDLEY_DIAGNOSTIC_POP + #else + #define SIMDE_MATH_HAVE_MATH_H + #include + #endif +#endif + +#if !defined(SIMDE_MATH_INFINITY) + #if \ + HEDLEY_HAS_BUILTIN(__builtin_inf) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) + #define SIMDE_MATH_INFINITY (__builtin_inf()) + #elif defined(INFINITY) + #define SIMDE_MATH_INFINITY INFINITY + #endif +#endif + +#if !defined(SIMDE_INFINITYF) + #if \ + HEDLEY_HAS_BUILTIN(__builtin_inff) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) + #define SIMDE_MATH_INFINITYF (__builtin_inff()) + #elif defined(INFINITYF) + #define SIMDE_MATH_INFINITYF INFINITYF + #elif defined(SIMDE_MATH_INFINITY) + #define SIMDE_MATH_INFINITYF HEDLEY_STATIC_CAST(float, SIMDE_MATH_INFINITY) + #endif +#endif + +#if !defined(SIMDE_MATH_NAN) + #if \ + HEDLEY_HAS_BUILTIN(__builtin_nan) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) + #define SIMDE_MATH_NAN (__builtin_nan("")) + #elif defined(NAN) + #define SIMDE_MATH_NAN NAN + #endif +#endif + +#if !defined(SIMDE_NANF) + #if \ + HEDLEY_HAS_BUILTIN(__builtin_nanf) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) + #define SIMDE_MATH_NANF (__builtin_nanf("")) + #elif defined(NANF) + #define SIMDE_MATH_NANF NANF + #elif defined(SIMDE_MATH_NAN) + #define SIMDE_MATH_NANF HEDLEY_STATIC_CAST(float, SIMDE_MATH_NAN) + #endif +#endif + +#if !defined(SIMDE_MATH_PI) + #if defined(M_PI) + #define SIMDE_MATH_PI M_PI + #else + #define SIMDE_MATH_PI 3.14159265358979323846 + #endif +#endif + +#if !defined(SIMDE_MATH_PIF) + #if defined(M_PI) + #define SIMDE_MATH_PIF HEDLEY_STATIC_CAST(float, M_PI) + #else + #define SIMDE_MATH_PIF 3.14159265358979323846f + #endif +#endif + +#if !defined(SIMDE_MATH_PI_OVER_180) + #define SIMDE_MATH_PI_OVER_180 0.0174532925199432957692369076848861271344287188854172545609719144 +#endif + +#if !defined(SIMDE_MATH_PI_OVER_180F) + #define SIMDE_MATH_PI_OVER_180F 0.0174532925199432957692369076848861271344287188854172545609719144f +#endif + +#if !defined(SIMDE_MATH_180_OVER_PI) + #define SIMDE_MATH_180_OVER_PI 57.295779513082320876798154814105170332405472466564321549160243861 +#endif + +#if !defined(SIMDE_MATH_180_OVER_PIF) + #define SIMDE_MATH_180_OVER_PIF 57.295779513082320876798154814105170332405472466564321549160243861f +#endif + +#if !defined(SIMDE_MATH_FLT_MIN) + #if defined(FLT_MIN) + #define SIMDE_MATH_FLT_MIN FLT_MIN + #elif defined(__FLT_MIN__) + #define SIMDE_MATH_FLT_MIN __FLT_MIN__ + #elif defined(__cplusplus) + #include + #define SIMDE_MATH_FLT_MIN FLT_MIN + #else + #include + #define SIMDE_MATH_FLT_MIN FLT_MIN + #endif +#endif + +#if !defined(SIMDE_MATH_DBL_MIN) + #if defined(DBL_MIN) + #define SIMDE_MATH_DBL_MIN DBL_MIN + #elif defined(__DBL_MIN__) + #define SIMDE_MATH_DBL_MIN __DBL_MIN__ + #elif defined(__cplusplus) + #include + #define SIMDE_MATH_DBL_MIN DBL_MIN + #else + #include + #define SIMDE_MATH_DBL_MIN DBL_MIN + #endif +#endif + +/*** Classification macros from C99 ***/ + +#if !defined(simde_math_isinf) + #if SIMDE_MATH_BUILTIN_LIBM(isinf) + #define simde_math_isinf(v) __builtin_isinf(v) + #elif defined(isinf) || defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_isinf(v) isinf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_isinf(v) std::isinf(v) + #endif +#endif + +#if !defined(simde_math_isinff) + #if HEDLEY_HAS_BUILTIN(__builtin_isinff) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define simde_math_isinff(v) __builtin_isinff(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_isinff(v) std::isinf(v) + #elif defined(simde_math_isinf) + #define simde_math_isinff(v) simde_math_isinf(HEDLEY_STATIC_CAST(double, v)) + #endif +#endif + +#if !defined(simde_math_isnan) + #if SIMDE_MATH_BUILTIN_LIBM(isnan) + #define simde_math_isnan(v) __builtin_isnan(v) + #elif defined(isnan) || defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_isnan(v) isnan(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_isnan(v) std::isnan(v) + #endif +#endif + +#if !defined(simde_math_isnanf) + #if HEDLEY_HAS_BUILTIN(__builtin_isnanf) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) + /* XL C/C++ has __builtin_isnan but not __builtin_isnanf */ + #define simde_math_isnanf(v) __builtin_isnanf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_isnanf(v) std::isnan(v) + #elif defined(simde_math_isnan) + #define simde_math_isnanf(v) simde_math_isnan(HEDLEY_STATIC_CAST(double, v)) + #endif +#endif + +#if !defined(simde_math_isnormal) + #if SIMDE_MATH_BUILTIN_LIBM(isnormal) + #define simde_math_isnormal(v) __builtin_isnormal(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_isnormal(v) isnormal(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_isnormal(v) std::isnormal(v) + #endif +#endif + +#if !defined(simde_math_isnormalf) + #if HEDLEY_HAS_BUILTIN(__builtin_isnormalf) + #define simde_math_isnormalf(v) __builtin_isnormalf(v) + #elif SIMDE_MATH_BUILTIN_LIBM(isnormal) + #define simde_math_isnormalf(v) __builtin_isnormal(v) + #elif defined(isnormalf) + #define simde_math_isnormalf(v) isnormalf(v) + #elif defined(isnormal) || defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_isnormalf(v) isnormal(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_isnormalf(v) std::isnormal(v) + #elif defined(simde_math_isnormal) + #define simde_math_isnormalf(v) simde_math_isnormal(v) + #endif +#endif + +/*** Manipulation functions ***/ + +#if !defined(simde_math_nextafter) + #if \ + (HEDLEY_HAS_BUILTIN(__builtin_nextafter) && !defined(HEDLEY_IBM_VERSION)) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define simde_math_nextafter(x, y) __builtin_nextafter(x, y) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_nextafter(x, y) std::nextafter(x, y) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_nextafter(x, y) nextafter(x, y) + #endif +#endif + +#if !defined(simde_math_nextafterf) + #if \ + (HEDLEY_HAS_BUILTIN(__builtin_nextafterf) && !defined(HEDLEY_IBM_VERSION)) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define simde_math_nextafterf(x, y) __builtin_nextafterf(x, y) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_nextafterf(x, y) std::nextafter(x, y) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_nextafterf(x, y) nextafterf(x, y) + #endif +#endif + +/*** Functions from C99 ***/ + +#if !defined(simde_math_abs) + #if SIMDE_MATH_BUILTIN_LIBM(abs) + #define simde_math_abs(v) __builtin_abs(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_abs(v) std::abs(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_abs(v) abs(v) + #endif +#endif + +#if !defined(simde_math_fabsf) + #if SIMDE_MATH_BUILTIN_LIBM(fabsf) + #define simde_math_fabsf(v) __builtin_fabsf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fabsf(v) std::abs(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fabsf(v) fabsf(v) + #endif +#endif + +#if !defined(simde_math_acos) + #if SIMDE_MATH_BUILTIN_LIBM(acos) + #define simde_math_acos(v) __builtin_acos(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_acos(v) std::acos(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_acos(v) acos(v) + #endif +#endif + +#if !defined(simde_math_acosf) + #if SIMDE_MATH_BUILTIN_LIBM(acosf) + #define simde_math_acosf(v) __builtin_acosf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_acosf(v) std::acos(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_acosf(v) acosf(v) + #endif +#endif + +#if !defined(simde_math_acosh) + #if SIMDE_MATH_BUILTIN_LIBM(acosh) + #define simde_math_acosh(v) __builtin_acosh(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_acosh(v) std::acosh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_acosh(v) acosh(v) + #endif +#endif + +#if !defined(simde_math_acoshf) + #if SIMDE_MATH_BUILTIN_LIBM(acoshf) + #define simde_math_acoshf(v) __builtin_acoshf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_acoshf(v) std::acosh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_acoshf(v) acoshf(v) + #endif +#endif + +#if !defined(simde_math_asin) + #if SIMDE_MATH_BUILTIN_LIBM(asin) + #define simde_math_asin(v) __builtin_asin(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_asin(v) std::asin(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_asin(v) asin(v) + #endif +#endif + +#if !defined(simde_math_asinf) + #if SIMDE_MATH_BUILTIN_LIBM(asinf) + #define simde_math_asinf(v) __builtin_asinf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_asinf(v) std::asin(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_asinf(v) asinf(v) + #endif +#endif + +#if !defined(simde_math_asinh) + #if SIMDE_MATH_BUILTIN_LIBM(asinh) + #define simde_math_asinh(v) __builtin_asinh(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_asinh(v) std::asinh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_asinh(v) asinh(v) + #endif +#endif + +#if !defined(simde_math_asinhf) + #if SIMDE_MATH_BUILTIN_LIBM(asinhf) + #define simde_math_asinhf(v) __builtin_asinhf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_asinhf(v) std::asinh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_asinhf(v) asinhf(v) + #endif +#endif + +#if !defined(simde_math_atan) + #if SIMDE_MATH_BUILTIN_LIBM(atan) + #define simde_math_atan(v) __builtin_atan(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_atan(v) std::atan(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_atan(v) atan(v) + #endif +#endif + +#if !defined(simde_math_atan2) + #if SIMDE_MATH_BUILTIN_LIBM(atan2) + #define simde_math_atan2(y, x) __builtin_atan2(y, x) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_atan2(y, x) std::atan2(y, x) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_atan2(y, x) atan2(y, x) + #endif +#endif + +#if !defined(simde_math_atan2f) + #if SIMDE_MATH_BUILTIN_LIBM(atan2f) + #define simde_math_atan2f(y, x) __builtin_atan2f(y, x) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_atan2f(y, x) std::atan2(y, x) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_atan2f(y, x) atan2f(y, x) + #endif +#endif + +#if !defined(simde_math_atanf) + #if SIMDE_MATH_BUILTIN_LIBM(atanf) + #define simde_math_atanf(v) __builtin_atanf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_atanf(v) std::atan(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_atanf(v) atanf(v) + #endif +#endif + +#if !defined(simde_math_atanh) + #if SIMDE_MATH_BUILTIN_LIBM(atanh) + #define simde_math_atanh(v) __builtin_atanh(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_atanh(v) std::atanh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_atanh(v) atanh(v) + #endif +#endif + +#if !defined(simde_math_atanhf) + #if SIMDE_MATH_BUILTIN_LIBM(atanhf) + #define simde_math_atanhf(v) __builtin_atanhf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_atanhf(v) std::atanh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_atanhf(v) atanhf(v) + #endif +#endif + +#if !defined(simde_math_cbrt) + #if SIMDE_MATH_BUILTIN_LIBM(cbrt) + #define simde_math_cbrt(v) __builtin_cbrt(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_cbrt(v) std::cbrt(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_cbrt(v) cbrt(v) + #endif +#endif + +#if !defined(simde_math_cbrtf) + #if SIMDE_MATH_BUILTIN_LIBM(cbrtf) + #define simde_math_cbrtf(v) __builtin_cbrtf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_cbrtf(v) std::cbrt(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_cbrtf(v) cbrtf(v) + #endif +#endif + +#if !defined(simde_math_ceil) + #if SIMDE_MATH_BUILTIN_LIBM(ceil) + #define simde_math_ceil(v) __builtin_ceil(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_ceil(v) std::ceil(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_ceil(v) ceil(v) + #endif +#endif + +#if !defined(simde_math_ceilf) + #if SIMDE_MATH_BUILTIN_LIBM(ceilf) + #define simde_math_ceilf(v) __builtin_ceilf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_ceilf(v) std::ceil(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_ceilf(v) ceilf(v) + #endif +#endif + +#if !defined(simde_math_copysign) + #if SIMDE_MATH_BUILTIN_LIBM(copysign) + #define simde_math_copysign(x, y) __builtin_copysign(x, y) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_copysign(x, y) std::copysign(x, y) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_copysign(x, y) copysign(x, y) + #endif +#endif + +#if !defined(simde_math_copysignf) + #if SIMDE_MATH_BUILTIN_LIBM(copysignf) + #define simde_math_copysignf(x, y) __builtin_copysignf(x, y) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_copysignf(x, y) std::copysignf(x, y) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_copysignf(x, y) copysignf(x, y) + #endif +#endif + +#if !defined(simde_math_cos) + #if SIMDE_MATH_BUILTIN_LIBM(cos) + #define simde_math_cos(v) __builtin_cos(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_cos(v) std::cos(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_cos(v) cos(v) + #endif +#endif + +#if !defined(simde_math_cosf) + #if defined(SIMDE_MATH_SLEEF_ENABLE) + #if SIMDE_ACCURACY_PREFERENCE < 1 + #define simde_math_cosf(v) Sleef_cosf_u35(v) + #else + #define simde_math_cosf(v) Sleef_cosf_u10(v) + #endif + #elif SIMDE_MATH_BUILTIN_LIBM(cosf) + #define simde_math_cosf(v) __builtin_cosf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_cosf(v) std::cos(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_cosf(v) cosf(v) + #endif +#endif + +#if !defined(simde_math_cosh) + #if SIMDE_MATH_BUILTIN_LIBM(cosh) + #define simde_math_cosh(v) __builtin_cosh(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_cosh(v) std::cosh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_cosh(v) cosh(v) + #endif +#endif + +#if !defined(simde_math_coshf) + #if SIMDE_MATH_BUILTIN_LIBM(coshf) + #define simde_math_coshf(v) __builtin_coshf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_coshf(v) std::cosh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_coshf(v) coshf(v) + #endif +#endif + +#if !defined(simde_math_erf) + #if SIMDE_MATH_BUILTIN_LIBM(erf) + #define simde_math_erf(v) __builtin_erf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_erf(v) std::erf(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_erf(v) erf(v) + #endif +#endif + +#if !defined(simde_math_erff) + #if SIMDE_MATH_BUILTIN_LIBM(erff) + #define simde_math_erff(v) __builtin_erff(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_erff(v) std::erf(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_erff(v) erff(v) + #endif +#endif + +#if !defined(simde_math_erfc) + #if SIMDE_MATH_BUILTIN_LIBM(erfc) + #define simde_math_erfc(v) __builtin_erfc(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_erfc(v) std::erfc(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_erfc(v) erfc(v) + #endif +#endif + +#if !defined(simde_math_erfcf) + #if SIMDE_MATH_BUILTIN_LIBM(erfcf) + #define simde_math_erfcf(v) __builtin_erfcf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_erfcf(v) std::erfc(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_erfcf(v) erfcf(v) + #endif +#endif + +#if !defined(simde_math_exp) + #if SIMDE_MATH_BUILTIN_LIBM(exp) + #define simde_math_exp(v) __builtin_exp(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_exp(v) std::exp(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_exp(v) exp(v) + #endif +#endif + +#if !defined(simde_math_expf) + #if SIMDE_MATH_BUILTIN_LIBM(expf) + #define simde_math_expf(v) __builtin_expf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_expf(v) std::exp(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_expf(v) expf(v) + #endif +#endif + +#if !defined(simde_math_expm1) + #if SIMDE_MATH_BUILTIN_LIBM(expm1) + #define simde_math_expm1(v) __builtin_expm1(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_expm1(v) std::expm1(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_expm1(v) expm1(v) + #endif +#endif + +#if !defined(simde_math_expm1f) + #if SIMDE_MATH_BUILTIN_LIBM(expm1f) + #define simde_math_expm1f(v) __builtin_expm1f(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_expm1f(v) std::expm1(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_expm1f(v) expm1f(v) + #endif +#endif + +#if !defined(simde_math_exp2) + #if SIMDE_MATH_BUILTIN_LIBM(exp2) + #define simde_math_exp2(v) __builtin_exp2(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_exp2(v) std::exp2(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_exp2(v) exp2(v) + #endif +#endif + +#if !defined(simde_math_exp2f) + #if SIMDE_MATH_BUILTIN_LIBM(exp2f) + #define simde_math_exp2f(v) __builtin_exp2f(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_exp2f(v) std::exp2(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_exp2f(v) exp2f(v) + #endif +#endif + +#if HEDLEY_HAS_BUILTIN(__builtin_exp10) || HEDLEY_GCC_VERSION_CHECK(3,4,0) + # define simde_math_exp10(v) __builtin_exp10(v) +#else +# define simde_math_exp10(v) pow(10.0, (v)) +#endif + +#if HEDLEY_HAS_BUILTIN(__builtin_exp10f) || HEDLEY_GCC_VERSION_CHECK(3,4,0) + # define simde_math_exp10f(v) __builtin_exp10f(v) +#else +# define simde_math_exp10f(v) powf(10.0f, (v)) +#endif + +#if !defined(simde_math_fabs) + #if SIMDE_MATH_BUILTIN_LIBM(fabs) + #define simde_math_fabs(v) __builtin_fabs(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fabs(v) std::fabs(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fabs(v) fabs(v) + #endif +#endif + +#if !defined(simde_math_fabsf) + #if SIMDE_MATH_BUILTIN_LIBM(fabsf) + #define simde_math_fabsf(v) __builtin_fabsf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fabsf(v) std::fabs(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fabsf(v) fabsf(v) + #endif +#endif + +#if !defined(simde_math_floor) + #if SIMDE_MATH_BUILTIN_LIBM(floor) + #define simde_math_floor(v) __builtin_floor(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_floor(v) std::floor(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_floor(v) floor(v) + #endif +#endif + +#if !defined(simde_math_floorf) + #if SIMDE_MATH_BUILTIN_LIBM(floorf) + #define simde_math_floorf(v) __builtin_floorf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_floorf(v) std::floor(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_floorf(v) floorf(v) + #endif +#endif + +#if !defined(simde_math_fma) + #if SIMDE_MATH_BUILTIN_LIBM(fma) + #define simde_math_fma(x, y, z) __builtin_fma(x, y, z) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fma(x, y, z) std::fma(x, y, z) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fma(x, y, z) fma(x, y, z) + #endif +#endif + +#if !defined(simde_math_fmaf) + #if SIMDE_MATH_BUILTIN_LIBM(fmaf) + #define simde_math_fmaf(x, y, z) __builtin_fmaf(x, y, z) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fmaf(x, y, z) std::fma(x, y, z) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fmaf(x, y, z) fmaf(x, y, z) + #endif +#endif + +#if !defined(simde_math_fmax) + #if SIMDE_MATH_BUILTIN_LIBM(fmax) + #define simde_math_fmax(x, y, z) __builtin_fmax(x, y, z) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fmax(x, y, z) std::fmax(x, y, z) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fmax(x, y, z) fmax(x, y, z) + #endif +#endif + +#if !defined(simde_math_fmaxf) + #if SIMDE_MATH_BUILTIN_LIBM(fmaxf) + #define simde_math_fmaxf(x, y, z) __builtin_fmaxf(x, y, z) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_fmaxf(x, y, z) std::fmax(x, y, z) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_fmaxf(x, y, z) fmaxf(x, y, z) + #endif +#endif + +#if !defined(simde_math_hypot) + #if SIMDE_MATH_BUILTIN_LIBM(hypot) + #define simde_math_hypot(y, x) __builtin_hypot(y, x) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_hypot(y, x) std::hypot(y, x) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_hypot(y, x) hypot(y, x) + #endif +#endif + +#if !defined(simde_math_hypotf) + #if SIMDE_MATH_BUILTIN_LIBM(hypotf) + #define simde_math_hypotf(y, x) __builtin_hypotf(y, x) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_hypotf(y, x) std::hypot(y, x) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_hypotf(y, x) hypotf(y, x) + #endif +#endif + +#if !defined(simde_math_log) + #if SIMDE_MATH_BUILTIN_LIBM(log) + #define simde_math_log(v) __builtin_log(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log(v) std::log(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log(v) log(v) + #endif +#endif + +#if !defined(simde_math_logf) + #if SIMDE_MATH_BUILTIN_LIBM(logf) + #define simde_math_logf(v) __builtin_logf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_logf(v) std::log(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_logf(v) logf(v) + #endif +#endif + +#if !defined(simde_math_logb) + #if SIMDE_MATH_BUILTIN_LIBM(logb) + #define simde_math_logb(v) __builtin_logb(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_logb(v) std::logb(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_logb(v) logb(v) + #endif +#endif + +#if !defined(simde_math_logbf) + #if SIMDE_MATH_BUILTIN_LIBM(logbf) + #define simde_math_logbf(v) __builtin_logbf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_logbf(v) std::logb(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_logbf(v) logbf(v) + #endif +#endif + +#if !defined(simde_math_log1p) + #if SIMDE_MATH_BUILTIN_LIBM(log1p) + #define simde_math_log1p(v) __builtin_log1p(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log1p(v) std::log1p(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log1p(v) log1p(v) + #endif +#endif + +#if !defined(simde_math_log1pf) + #if SIMDE_MATH_BUILTIN_LIBM(log1pf) + #define simde_math_log1pf(v) __builtin_log1pf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log1pf(v) std::log1p(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log1pf(v) log1pf(v) + #endif +#endif + +#if !defined(simde_math_log2) + #if SIMDE_MATH_BUILTIN_LIBM(log2) + #define simde_math_log2(v) __builtin_log2(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log2(v) std::log2(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log2(v) log2(v) + #endif +#endif + +#if !defined(simde_math_log2f) + #if SIMDE_MATH_BUILTIN_LIBM(log2f) + #define simde_math_log2f(v) __builtin_log2f(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log2f(v) std::log2(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log2f(v) log2f(v) + #endif +#endif + +#if !defined(simde_math_log10) + #if SIMDE_MATH_BUILTIN_LIBM(log10) + #define simde_math_log10(v) __builtin_log10(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log10(v) std::log10(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log10(v) log10(v) + #endif +#endif + +#if !defined(simde_math_log10f) + #if SIMDE_MATH_BUILTIN_LIBM(log10f) + #define simde_math_log10f(v) __builtin_log10f(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_log10f(v) std::log10(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_log10f(v) log10f(v) + #endif +#endif + +#if !defined(simde_math_modf) + #if SIMDE_MATH_BUILTIN_LIBM(modf) + #define simde_math_modf(x, iptr) __builtin_modf(x, iptr) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_modf(x, iptr) std::modf(x, iptr) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_modf(x, iptr) modf(x, iptr) + #endif +#endif + +#if !defined(simde_math_modff) + #if SIMDE_MATH_BUILTIN_LIBM(modff) + #define simde_math_modff(x, iptr) __builtin_modff(x, iptr) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_modff(x, iptr) std::modf(x, iptr) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_modff(x, iptr) modff(x, iptr) + #endif +#endif + +#if !defined(simde_math_nearbyint) + #if SIMDE_MATH_BUILTIN_LIBM(nearbyint) + #define simde_math_nearbyint(v) __builtin_nearbyint(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_nearbyint(v) std::nearbyint(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_nearbyint(v) nearbyint(v) + #endif +#endif + +#if !defined(simde_math_nearbyintf) + #if SIMDE_MATH_BUILTIN_LIBM(nearbyintf) + #define simde_math_nearbyintf(v) __builtin_nearbyintf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_nearbyintf(v) std::nearbyint(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_nearbyintf(v) nearbyintf(v) + #endif +#endif + +#if !defined(simde_math_pow) + #if SIMDE_MATH_BUILTIN_LIBM(pow) + #define simde_math_pow(y, x) __builtin_pow(y, x) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_pow(y, x) std::pow(y, x) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_pow(y, x) pow(y, x) + #endif +#endif + +#if !defined(simde_math_powf) + #if SIMDE_MATH_BUILTIN_LIBM(powf) + #define simde_math_powf(y, x) __builtin_powf(y, x) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_powf(y, x) std::pow(y, x) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_powf(y, x) powf(y, x) + #endif +#endif + +#if !defined(simde_math_rint) + #if SIMDE_MATH_BUILTIN_LIBM(rint) + #define simde_math_rint(v) __builtin_rint(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_rint(v) std::rint(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_rint(v) rint(v) + #endif +#endif + +#if !defined(simde_math_rintf) + #if SIMDE_MATH_BUILTIN_LIBM(rintf) + #define simde_math_rintf(v) __builtin_rintf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_rintf(v) std::rint(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_rintf(v) rintf(v) + #endif +#endif + +#if !defined(simde_math_round) + #if SIMDE_MATH_BUILTIN_LIBM(round) + #define simde_math_round(v) __builtin_round(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_round(v) std::round(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_round(v) round(v) + #endif +#endif + +#if !defined(simde_math_roundf) + #if SIMDE_MATH_BUILTIN_LIBM(roundf) + #define simde_math_roundf(v) __builtin_roundf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_roundf(v) std::round(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_roundf(v) roundf(v) + #endif +#endif + +#if !defined(simde_math_roundeven) + #if \ + HEDLEY_HAS_BUILTIN(__builtin_roundeven) || \ + HEDLEY_GCC_VERSION_CHECK(10,0,0) + #define simde_math_roundeven(v) __builtin_roundeven(v) + #elif defined(simde_math_round) && defined(simde_math_fabs) + static HEDLEY_INLINE + double + simde_math_roundeven(double v) { + double rounded = simde_math_round(v); + double diff = rounded - v; + if (HEDLEY_UNLIKELY(simde_math_fabs(diff) == 0.5) && (HEDLEY_STATIC_CAST(int64_t, rounded) & 1)) { + rounded = v - diff; + } + return rounded; + } + #define simde_math_roundeven simde_math_roundeven + #endif +#endif + +#if !defined(simde_math_roundevenf) + #if \ + HEDLEY_HAS_BUILTIN(__builtin_roundevenf) || \ + HEDLEY_GCC_VERSION_CHECK(10,0,0) + #define simde_math_roundevenf(v) __builtin_roundevenf(v) + #elif defined(simde_math_roundf) && defined(simde_math_fabsf) + static HEDLEY_INLINE + float + simde_math_roundevenf(float v) { + float rounded = simde_math_roundf(v); + float diff = rounded - v; + if (HEDLEY_UNLIKELY(simde_math_fabsf(diff) == 0.5f) && (HEDLEY_STATIC_CAST(int32_t, rounded) & 1)) { + rounded = v - diff; + } + return rounded; + } + #define simde_math_roundevenf simde_math_roundevenf + #endif +#endif + +#if !defined(simde_math_sin) + #if SIMDE_MATH_BUILTIN_LIBM(sin) + #define simde_math_sin(v) __builtin_sin(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_sin(v) std::sin(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_sin(v) sin(v) + #endif +#endif + +#if !defined(simde_math_sinf) + #if SIMDE_MATH_BUILTIN_LIBM(sinf) + #define simde_math_sinf(v) __builtin_sinf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_sinf(v) std::sin(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_sinf(v) sinf(v) + #endif +#endif + +#if !defined(simde_math_sinh) + #if SIMDE_MATH_BUILTIN_LIBM(sinh) + #define simde_math_sinh(v) __builtin_sinh(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_sinh(v) std::sinh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_sinh(v) sinh(v) + #endif +#endif + +#if !defined(simde_math_sinhf) + #if SIMDE_MATH_BUILTIN_LIBM(sinhf) + #define simde_math_sinhf(v) __builtin_sinhf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_sinhf(v) std::sinh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_sinhf(v) sinhf(v) + #endif +#endif + +#if !defined(simde_math_sqrt) + #if SIMDE_MATH_BUILTIN_LIBM(sqrt) + #define simde_math_sqrt(v) __builtin_sqrt(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_sqrt(v) std::sqrt(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_sqrt(v) sqrt(v) + #endif +#endif + +#if !defined(simde_math_sqrtf) + #if SIMDE_MATH_BUILTIN_LIBM(sqrtf) + #define simde_math_sqrtf(v) __builtin_sqrtf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_sqrtf(v) std::sqrt(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_sqrtf(v) sqrtf(v) + #endif +#endif + +#if !defined(simde_math_tan) + #if SIMDE_MATH_BUILTIN_LIBM(tan) + #define simde_math_tan(v) __builtin_tan(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_tan(v) std::tan(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_tan(v) tan(v) + #endif +#endif + +#if !defined(simde_math_tanf) + #if SIMDE_MATH_BUILTIN_LIBM(tanf) + #define simde_math_tanf(v) __builtin_tanf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_tanf(v) std::tan(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_tanf(v) tanf(v) + #endif +#endif + +#if !defined(simde_math_tanh) + #if SIMDE_MATH_BUILTIN_LIBM(tanh) + #define simde_math_tanh(v) __builtin_tanh(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_tanh(v) std::tanh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_tanh(v) tanh(v) + #endif +#endif + +#if !defined(simde_math_tanhf) + #if SIMDE_MATH_BUILTIN_LIBM(tanhf) + #define simde_math_tanhf(v) __builtin_tanhf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_tanhf(v) std::tanh(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_tanhf(v) tanhf(v) + #endif +#endif + +#if !defined(simde_math_trunc) + #if SIMDE_MATH_BUILTIN_LIBM(trunc) + #define simde_math_trunc(v) __builtin_trunc(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_trunc(v) std::trunc(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_trunc(v) trunc(v) + #endif +#endif + +#if !defined(simde_math_truncf) + #if SIMDE_MATH_BUILTIN_LIBM(truncf) + #define simde_math_truncf(v) __builtin_truncf(v) + #elif defined(SIMDE_MATH_HAVE_CMATH) + #define simde_math_truncf(v) std::trunc(v) + #elif defined(SIMDE_MATH_HAVE_MATH_H) + #define simde_math_truncf(v) truncf(v) + #endif +#endif + +/*** Comparison macros (which don't raise invalid errors) ***/ + +#if defined(isunordered) + #define simde_math_isunordered(x, y) isunordered(x, y) +#elif HEDLEY_HAS_BUILTIN(__builtin_isunordered) + #define simde_math_isunordered(x, y) __builtin_isunordered(x, y) +#else + static HEDLEY_INLINE + int simde_math_isunordered(double x, double y) { + return (x != y) && (x != x || y != y); + } + #define simde_math_isunordered simde_math_isunordered + + static HEDLEY_INLINE + int simde_math_isunorderedf(float x, float y) { + return (x != y) && (x != x || y != y); + } + #define simde_math_isunorderedf simde_math_isunorderedf +#endif +#if !defined(simde_math_isunorderedf) + #define simde_math_isunorderedf simde_math_isunordered +#endif + +/*** Additional functions not in libm ***/ + +#if defined(simde_math_fabs) && defined(simde_math_sqrt) && defined(simde_math_exp) + static HEDLEY_INLINE + double + simde_math_cdfnorm(double x) { + /* https://www.johndcook.com/blog/cpp_phi/ + * Public Domain */ + static const double a1 = 0.254829592; + static const double a2 = -0.284496736; + static const double a3 = 1.421413741; + static const double a4 = -1.453152027; + static const double a5 = 1.061405429; + static const double p = 0.3275911; + + const int sign = x < 0; + x = simde_math_fabs(x) / simde_math_sqrt(2.0); + + /* A&S formula 7.1.26 */ + double t = 1.0 / (1.0 + p * x); + double y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * simde_math_exp(-x * x); + + return 0.5 * (1.0 + (sign ? -y : y)); + } + #define simde_math_cdfnorm simde_math_cdfnorm +#endif + +#if defined(simde_math_fabsf) && defined(simde_math_sqrtf) && defined(simde_math_expf) + static HEDLEY_INLINE + float + simde_math_cdfnormf(float x) { + /* https://www.johndcook.com/blog/cpp_phi/ + * Public Domain */ + static const float a1 = 0.254829592f; + static const float a2 = -0.284496736f; + static const float a3 = 1.421413741f; + static const float a4 = -1.453152027f; + static const float a5 = 1.061405429f; + static const float p = 0.3275911f; + + const int sign = x < 0; + x = simde_math_fabsf(x) / simde_math_sqrtf(2.0f); + + /* A&S formula 7.1.26 */ + float t = 1.0f / (1.0f + p * x); + float y = 1.0f - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * simde_math_expf(-x * x); + + return 0.5f * (1.0f + (sign ? -y : y)); + } + #define simde_math_cdfnormf simde_math_cdfnormf +#endif + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL_ + +#if !defined(simde_math_cdfnorminv) && defined(simde_math_log) && defined(simde_math_sqrt) + /*https://web.archive.org/web/20150910081113/http://home.online.no/~pjacklam/notes/invnorm/impl/sprouse/ltqnorm.c*/ + static HEDLEY_INLINE + double + simde_math_cdfnorminv(double p) { + static const double a[] = { + -3.969683028665376e+01, + 2.209460984245205e+02, + -2.759285104469687e+02, + 1.383577518672690e+02, + -3.066479806614716e+01, + 2.506628277459239e+00 + }; + + static const double b[] = { + -5.447609879822406e+01, + 1.615858368580409e+02, + -1.556989798598866e+02, + 6.680131188771972e+01, + -1.328068155288572e+01 + }; + + static const double c[] = { + -7.784894002430293e-03, + -3.223964580411365e-01, + -2.400758277161838e+00, + -2.549732539343734e+00, + 4.374664141464968e+00, + 2.938163982698783e+00 + }; + + static const double d[] = { + 7.784695709041462e-03, + 3.224671290700398e-01, + 2.445134137142996e+00, + 3.754408661907416e+00 + }; + + static const double low = 0.02425; + static const double high = 0.97575; + double q, r; + + if (p < 0 || p > 1) { + return 0.0; + } else if (p == 0) { + return -SIMDE_MATH_INFINITY; + } else if (p == 1) { + return SIMDE_MATH_INFINITY; + } else if (p < low) { + q = simde_math_sqrt(-2.0 * simde_math_log(p)); + return + (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / + (((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1)); + } else if (p > high) { + q = simde_math_sqrt(-2.0 * simde_math_log(1.0 - p)); + return + -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / + (((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1)); + } else { + q = p - 0.5; + r = q * q; + return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * + q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1); + } +} +#define simde_math_cdfnorminv simde_math_cdfnorminv +#endif + +#if !defined(simde_math_cdfnorminvf) && defined(simde_math_logf) && defined(simde_math_sqrtf) + static HEDLEY_INLINE + float + simde_math_cdfnorminvf(float p) { + static const float a[] = { + -3.969683028665376e+01f, + 2.209460984245205e+02f, + -2.759285104469687e+02f, + 1.383577518672690e+02f, + -3.066479806614716e+01f, + 2.506628277459239e+00f + }; + static const float b[] = { + -5.447609879822406e+01f, + 1.615858368580409e+02f, + -1.556989798598866e+02f, + 6.680131188771972e+01f, + -1.328068155288572e+01f + }; + static const float c[] = { + -7.784894002430293e-03f, + -3.223964580411365e-01f, + -2.400758277161838e+00f, + -2.549732539343734e+00f, + 4.374664141464968e+00f, + 2.938163982698783e+00f + }; + static const float d[] = { + 7.784695709041462e-03f, + 3.224671290700398e-01f, + 2.445134137142996e+00f, + 3.754408661907416e+00f + }; + static const float low = 0.02425f; + static const float high = 0.97575f; + float q, r; + + if (p < 0 || p > 1) { + return 0.0f; + } else if (p == 0) { + return -SIMDE_MATH_INFINITYF; + } else if (p == 1) { + return SIMDE_MATH_INFINITYF; + } else if (p < low) { + q = simde_math_sqrtf(-2.0f * simde_math_logf(p)); + return + (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / + (((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1)); + } else if (p > high) { + q = simde_math_sqrtf(-2.0f * simde_math_logf(1.0f - p)); + return + -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / + (((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1)); + } else { + q = p - 0.5f; + r = q * q; + return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * + q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1); + } + } + #define simde_math_cdfnorminvf simde_math_cdfnorminvf +#endif + +#if !defined(simde_math_erfinv) && defined(simde_math_log) && defined(simde_math_copysign) && defined(simde_math_sqrt) + static HEDLEY_INLINE + double + simde_math_erfinv(double x) { + /* https://stackoverflow.com/questions/27229371/inverse-error-function-in-c + * + * The original answer on SO uses a constant of 0.147, but in my + * testing 0.14829094707965850830078125 gives a lower average absolute error + * (0.0001410958211636170744895935 vs. 0.0001465479290345683693885803). + * That said, if your goal is to minimize the *maximum* absolute + * error, 0.15449436008930206298828125 provides significantly better + * results; 0.0009250640869140625000000000 vs ~ 0.005. */ + double tt1, tt2, lnx; + double sgn = simde_math_copysign(1.0, x); + + x = (1.0 - x) * (1.0 + x); + lnx = simde_math_log(x); + + tt1 = 2.0 / (SIMDE_MATH_PI * 0.14829094707965850830078125) + 0.5 * lnx; + tt2 = (1.0 / 0.14829094707965850830078125) * lnx; + + return sgn * simde_math_sqrt(-tt1 + simde_math_sqrt(tt1 * tt1 - tt2)); + } + #define simde_math_erfinv simde_math_erfinv +#endif + +#if !defined(simde_math_erfinvf) && defined(simde_math_logf) && defined(simde_math_copysignf) && defined(simde_math_sqrtf) + static HEDLEY_INLINE + float + simde_math_erfinvf(float x) { + float tt1, tt2, lnx; + float sgn = simde_math_copysignf(1.0f, x); + + x = (1.0f - x) * (1.0f + x); + lnx = simde_math_logf(x); + + tt1 = 2.0f / (SIMDE_MATH_PIF * 0.14829094707965850830078125f) + 0.5f * lnx; + tt2 = (1.0f / 0.14829094707965850830078125f) * lnx; + + return sgn * simde_math_sqrtf(-tt1 + simde_math_sqrtf(tt1 * tt1 - tt2)); + } + #define simde_math_erfinvf simde_math_erfinvf +#endif + +#if !defined(simde_math_erfcinv) && defined(simde_math_erfinv) && defined(simde_math_log) && defined(simde_math_sqrt) + static HEDLEY_INLINE + double + simde_math_erfcinv(double x) { + if(x >= 0.0625 && x < 2.0) { + return simde_math_erfinv(1.0 - x); + } else if (x < 0.0625 && x >= 1.0e-100) { + double p[6] = { + 0.1550470003116, + 1.382719649631, + 0.690969348887, + -1.128081391617, + 0.680544246825, + -0.16444156791 + }; + double q[3] = { + 0.155024849822, + 1.385228141995, + 1.000000000000 + }; + + const double t = 1.0 / simde_math_sqrt(-simde_math_log(x)); + return (p[0] / t + p[1] + t * (p[2] + t * (p[3] + t * (p[4] + t * p[5])))) / + (q[0] + t * (q[1] + t * (q[2]))); + } else if (x < 1.0e-100 && x >= SIMDE_MATH_DBL_MIN) { + double p[4] = { + 0.00980456202915, + 0.363667889171, + 0.97302949837, + -0.5374947401 + }; + double q[3] = { + 0.00980451277802, + 0.363699971544, + 1.000000000000 + }; + + const double t = 1.0 / simde_math_sqrt(-simde_math_log(x)); + return (p[0] / t + p[1] + t * (p[2] + t * p[3])) / + (q[0] + t * (q[1] + t * (q[2]))); + } else if (!simde_math_isnormal(x)) { + return SIMDE_MATH_INFINITY; + } else { + return -SIMDE_MATH_INFINITY; + } + } + + #define simde_math_erfcinv simde_math_erfcinv +#endif + +#if !defined(simde_math_erfcinvf) && defined(simde_math_erfinvf) && defined(simde_math_logf) && defined(simde_math_sqrtf) + static HEDLEY_INLINE + float + simde_math_erfcinvf(float x) { + if(x >= 0.0625f && x < 2.0f) { + return simde_math_erfinvf(1.0f - x); + } else if (x < 0.0625f && x >= SIMDE_MATH_FLT_MIN) { + static const float p[6] = { + 0.1550470003116f, + 1.382719649631f, + 0.690969348887f, + -1.128081391617f, + 0.680544246825f + -0.164441567910f + }; + static const float q[3] = { + 0.155024849822f, + 1.385228141995f, + 1.000000000000f + }; + + const float t = 1.0f / simde_math_sqrtf(-simde_math_logf(x)); + return (p[0] / t + p[1] + t * (p[2] + t * (p[3] + t * (p[4] + t * p[5])))) / + (q[0] + t * (q[1] + t * (q[2]))); + } else if (x < SIMDE_MATH_FLT_MIN && simde_math_isnormalf(x)) { + static const float p[4] = { + 0.00980456202915f, + 0.36366788917100f, + 0.97302949837000f, + -0.5374947401000f + }; + static const float q[3] = { + 0.00980451277802f, + 0.36369997154400f, + 1.00000000000000f + }; + + const float t = 1.0f / simde_math_sqrtf(-simde_math_logf(x)); + return (p[0] / t + p[1] + t * (p[2] + t * p[3])) / + (q[0] + t * (q[1] + t * (q[2]))); + } else { + return simde_math_isnormalf(x) ? -SIMDE_MATH_INFINITYF : SIMDE_MATH_INFINITYF; + } + } + + #define simde_math_erfcinvf simde_math_erfcinvf +#endif + +HEDLEY_DIAGNOSTIC_POP + +static HEDLEY_INLINE +double +simde_math_rad2deg(double radians) { + return radians * SIMDE_MATH_180_OVER_PI; +} + +static HEDLEY_INLINE +float +simde_math_rad2degf(float radians) { + return radians * SIMDE_MATH_180_OVER_PIF; +} + +static HEDLEY_INLINE +double +simde_math_deg2rad(double degrees) { + return degrees * SIMDE_MATH_PI_OVER_180; +} + +static HEDLEY_INLINE +float +simde_math_deg2radf(float degrees) { + return degrees * (SIMDE_MATH_PI_OVER_180F); +} + +/*** Saturated arithmetic ***/ + +static HEDLEY_INLINE +int8_t +simde_math_adds_i8(int8_t a, int8_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqaddb_s8(a, b); + #else + uint8_t a_ = HEDLEY_STATIC_CAST(uint8_t, a); + uint8_t b_ = HEDLEY_STATIC_CAST(uint8_t, b); + uint8_t r_ = a_ + b_; + + a_ = (a_ >> ((8 * sizeof(r_)) - 1)) + INT8_MAX; + if (HEDLEY_STATIC_CAST(int8_t, ((a_ ^ b_) | ~(b_ ^ r_))) >= 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int8_t, r_); + #endif +} + +static HEDLEY_INLINE +int16_t +simde_math_adds_i16(int16_t a, int16_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqaddh_s16(a, b); + #else + uint16_t a_ = HEDLEY_STATIC_CAST(uint16_t, a); + uint16_t b_ = HEDLEY_STATIC_CAST(uint16_t, b); + uint16_t r_ = a_ + b_; + + a_ = (a_ >> ((8 * sizeof(r_)) - 1)) + INT16_MAX; + if (HEDLEY_STATIC_CAST(int16_t, ((a_ ^ b_) | ~(b_ ^ r_))) >= 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int16_t, r_); + #endif +} + +static HEDLEY_INLINE +int32_t +simde_math_adds_i32(int32_t a, int32_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqadds_s32(a, b); + #else + uint32_t a_ = HEDLEY_STATIC_CAST(uint32_t, a); + uint32_t b_ = HEDLEY_STATIC_CAST(uint32_t, b); + uint32_t r_ = a_ + b_; + + a_ = (a_ >> ((8 * sizeof(r_)) - 1)) + INT32_MAX; + if (HEDLEY_STATIC_CAST(int32_t, ((a_ ^ b_) | ~(b_ ^ r_))) >= 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int32_t, r_); + #endif +} + +static HEDLEY_INLINE +int64_t +simde_math_adds_i64(int64_t a, int64_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqaddd_s64(a, b); + #else + uint64_t a_ = HEDLEY_STATIC_CAST(uint64_t, a); + uint64_t b_ = HEDLEY_STATIC_CAST(uint64_t, b); + uint64_t r_ = a_ + b_; + + a_ = (a_ >> ((8 * sizeof(r_)) - 1)) + INT64_MAX; + if (HEDLEY_STATIC_CAST(int64_t, ((a_ ^ b_) | ~(b_ ^ r_))) >= 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int64_t, r_); + #endif +} + +static HEDLEY_INLINE +uint8_t +simde_math_adds_u8(uint8_t a, uint8_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqaddb_u8(a, b); + #else + uint8_t r = a + b; + r |= -(r < a); + return r; + #endif +} + +static HEDLEY_INLINE +uint16_t +simde_math_adds_u16(uint16_t a, uint16_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqaddh_u16(a, b); + #else + uint16_t r = a + b; + r |= -(r < a); + return r; + #endif +} + +static HEDLEY_INLINE +uint32_t +simde_math_adds_u32(uint32_t a, uint32_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqadds_u32(a, b); + #else + uint32_t r = a + b; + r |= -(r < a); + return r; + #endif +} + +static HEDLEY_INLINE +uint64_t +simde_math_adds_u64(uint64_t a, uint64_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqaddd_u64(a, b); + #else + uint64_t r = a + b; + r |= -(r < a); + return r; + #endif +} + +static HEDLEY_INLINE +int8_t +simde_math_subs_i8(int8_t a, int8_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubb_s8(a, b); + #else + uint8_t a_ = HEDLEY_STATIC_CAST(uint8_t, a); + uint8_t b_ = HEDLEY_STATIC_CAST(uint8_t, b); + uint8_t r_ = a_ - b_; + + a_ = (a_ >> 7) + INT8_MAX; + + if (HEDLEY_STATIC_CAST(int8_t, (a_ ^ b_) & (a_ ^ r_)) < 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int8_t, r_); + #endif +} + +static HEDLEY_INLINE +int16_t +simde_math_subs_i16(int16_t a, int16_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubh_s16(a, b); + #else + uint16_t a_ = HEDLEY_STATIC_CAST(uint16_t, a); + uint16_t b_ = HEDLEY_STATIC_CAST(uint16_t, b); + uint16_t r_ = a_ - b_; + + a_ = (a_ >> 15) + INT16_MAX; + + if (HEDLEY_STATIC_CAST(int16_t, (a_ ^ b_) & (a_ ^ r_)) < 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int16_t, r_); + #endif +} + +static HEDLEY_INLINE +int32_t +simde_math_subs_i32(int32_t a, int32_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubs_s32(a, b); + #else + uint32_t a_ = HEDLEY_STATIC_CAST(uint32_t, a); + uint32_t b_ = HEDLEY_STATIC_CAST(uint32_t, b); + uint32_t r_ = a_ - b_; + + a_ = (a_ >> 31) + INT32_MAX; + + if (HEDLEY_STATIC_CAST(int32_t, (a_ ^ b_) & (a_ ^ r_)) < 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int32_t, r_); + #endif +} + +static HEDLEY_INLINE +int64_t +simde_math_subs_i64(int64_t a, int64_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubd_s64(a, b); + #else + uint64_t a_ = HEDLEY_STATIC_CAST(uint64_t, a); + uint64_t b_ = HEDLEY_STATIC_CAST(uint64_t, b); + uint64_t r_ = a_ - b_; + + a_ = (a_ >> 63) + INT64_MAX; + + if (HEDLEY_STATIC_CAST(int64_t, (a_ ^ b_) & (a_ ^ r_)) < 0) { + r_ = a_; + } + + return HEDLEY_STATIC_CAST(int64_t, r_); + #endif +} + +static HEDLEY_INLINE +uint8_t +simde_math_subs_u8(uint8_t a, uint8_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubb_u8(a, b); + #else + uint8_t res = a - b; + res &= -(res <= a); + return res; + #endif +} + +static HEDLEY_INLINE +uint16_t +simde_math_subs_u16(uint16_t a, uint16_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubh_u16(a, b); + #else + uint16_t res = a - b; + res &= -(res <= a); + return res; + #endif +} + +static HEDLEY_INLINE +uint32_t +simde_math_subs_u32(uint32_t a, uint32_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubs_u32(a, b); + #else + uint32_t res = a - b; + res &= -(res <= a); + return res; + #endif +} + +static HEDLEY_INLINE +uint64_t +simde_math_subs_u64(uint64_t a, uint64_t b) { + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vqsubd_u64(a, b); + #else + uint64_t res = a - b; + res &= -(res <= a); + return res; + #endif +} + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_MATH_H) */ +/* :: End ../simde/simde/simde-math.h :: */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-constify.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2020 Evan Nemerson + */ + +/* Constify macros. For internal use only. + * + * These are used to make it possible to call a function which takes + * an Integer Constant Expression (ICE) using a compile time constant. + * Technically it would also be possible to use a value not trivially + * known by the compiler, but there would be a siginficant performance + * hit (a switch switch is used). + * + * The basic idea is pretty simple; we just emit a do while loop which + * contains a switch with a case for every possible value of the + * constant. + * + * As long as the value you pass to the function in constant, pretty + * much any copmiler shouldn't have a problem generating exactly the + * same code as if you had used an ICE. + * + * This is intended to be used in the SIMDe implementations of + * functions the compilers require to be an ICE, but the other benefit + * is that if we also disable the warnings from + * SIMDE_REQUIRE_CONSTANT_RANGE we can actually just allow the tests + * to use non-ICE parameters + */ + +#if !defined(SIMDE_CONSTIFY_H) +#define SIMDE_CONSTIFY_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_ +SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_ + +#define SIMDE_CONSTIFY_2_(func_name, result, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: result = func_name(__VA_ARGS__, 0); break; \ + case 1: result = func_name(__VA_ARGS__, 1); break; \ + default: result = default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_4_(func_name, result, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: result = func_name(__VA_ARGS__, 0); break; \ + case 1: result = func_name(__VA_ARGS__, 1); break; \ + case 2: result = func_name(__VA_ARGS__, 2); break; \ + case 3: result = func_name(__VA_ARGS__, 3); break; \ + default: result = default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_8_(func_name, result, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: result = func_name(__VA_ARGS__, 0); break; \ + case 1: result = func_name(__VA_ARGS__, 1); break; \ + case 2: result = func_name(__VA_ARGS__, 2); break; \ + case 3: result = func_name(__VA_ARGS__, 3); break; \ + case 4: result = func_name(__VA_ARGS__, 4); break; \ + case 5: result = func_name(__VA_ARGS__, 5); break; \ + case 6: result = func_name(__VA_ARGS__, 6); break; \ + case 7: result = func_name(__VA_ARGS__, 7); break; \ + default: result = default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_16_(func_name, result, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: result = func_name(__VA_ARGS__, 0); break; \ + case 1: result = func_name(__VA_ARGS__, 1); break; \ + case 2: result = func_name(__VA_ARGS__, 2); break; \ + case 3: result = func_name(__VA_ARGS__, 3); break; \ + case 4: result = func_name(__VA_ARGS__, 4); break; \ + case 5: result = func_name(__VA_ARGS__, 5); break; \ + case 6: result = func_name(__VA_ARGS__, 6); break; \ + case 7: result = func_name(__VA_ARGS__, 7); break; \ + case 8: result = func_name(__VA_ARGS__, 8); break; \ + case 9: result = func_name(__VA_ARGS__, 9); break; \ + case 10: result = func_name(__VA_ARGS__, 10); break; \ + case 11: result = func_name(__VA_ARGS__, 11); break; \ + case 12: result = func_name(__VA_ARGS__, 12); break; \ + case 13: result = func_name(__VA_ARGS__, 13); break; \ + case 14: result = func_name(__VA_ARGS__, 14); break; \ + case 15: result = func_name(__VA_ARGS__, 15); break; \ + default: result = default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_32_(func_name, result, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: result = func_name(__VA_ARGS__, 0); break; \ + case 1: result = func_name(__VA_ARGS__, 1); break; \ + case 2: result = func_name(__VA_ARGS__, 2); break; \ + case 3: result = func_name(__VA_ARGS__, 3); break; \ + case 4: result = func_name(__VA_ARGS__, 4); break; \ + case 5: result = func_name(__VA_ARGS__, 5); break; \ + case 6: result = func_name(__VA_ARGS__, 6); break; \ + case 7: result = func_name(__VA_ARGS__, 7); break; \ + case 8: result = func_name(__VA_ARGS__, 8); break; \ + case 9: result = func_name(__VA_ARGS__, 9); break; \ + case 10: result = func_name(__VA_ARGS__, 10); break; \ + case 11: result = func_name(__VA_ARGS__, 11); break; \ + case 12: result = func_name(__VA_ARGS__, 12); break; \ + case 13: result = func_name(__VA_ARGS__, 13); break; \ + case 14: result = func_name(__VA_ARGS__, 14); break; \ + case 15: result = func_name(__VA_ARGS__, 15); break; \ + case 16: result = func_name(__VA_ARGS__, 16); break; \ + case 17: result = func_name(__VA_ARGS__, 17); break; \ + case 18: result = func_name(__VA_ARGS__, 18); break; \ + case 19: result = func_name(__VA_ARGS__, 19); break; \ + case 20: result = func_name(__VA_ARGS__, 20); break; \ + case 21: result = func_name(__VA_ARGS__, 21); break; \ + case 22: result = func_name(__VA_ARGS__, 22); break; \ + case 23: result = func_name(__VA_ARGS__, 23); break; \ + case 24: result = func_name(__VA_ARGS__, 24); break; \ + case 25: result = func_name(__VA_ARGS__, 25); break; \ + case 26: result = func_name(__VA_ARGS__, 26); break; \ + case 27: result = func_name(__VA_ARGS__, 27); break; \ + case 28: result = func_name(__VA_ARGS__, 28); break; \ + case 29: result = func_name(__VA_ARGS__, 29); break; \ + case 30: result = func_name(__VA_ARGS__, 30); break; \ + case 31: result = func_name(__VA_ARGS__, 31); break; \ + default: result = default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_64_(func_name, result, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: result = func_name(__VA_ARGS__, 0); break; \ + case 1: result = func_name(__VA_ARGS__, 1); break; \ + case 2: result = func_name(__VA_ARGS__, 2); break; \ + case 3: result = func_name(__VA_ARGS__, 3); break; \ + case 4: result = func_name(__VA_ARGS__, 4); break; \ + case 5: result = func_name(__VA_ARGS__, 5); break; \ + case 6: result = func_name(__VA_ARGS__, 6); break; \ + case 7: result = func_name(__VA_ARGS__, 7); break; \ + case 8: result = func_name(__VA_ARGS__, 8); break; \ + case 9: result = func_name(__VA_ARGS__, 9); break; \ + case 10: result = func_name(__VA_ARGS__, 10); break; \ + case 11: result = func_name(__VA_ARGS__, 11); break; \ + case 12: result = func_name(__VA_ARGS__, 12); break; \ + case 13: result = func_name(__VA_ARGS__, 13); break; \ + case 14: result = func_name(__VA_ARGS__, 14); break; \ + case 15: result = func_name(__VA_ARGS__, 15); break; \ + case 16: result = func_name(__VA_ARGS__, 16); break; \ + case 17: result = func_name(__VA_ARGS__, 17); break; \ + case 18: result = func_name(__VA_ARGS__, 18); break; \ + case 19: result = func_name(__VA_ARGS__, 19); break; \ + case 20: result = func_name(__VA_ARGS__, 20); break; \ + case 21: result = func_name(__VA_ARGS__, 21); break; \ + case 22: result = func_name(__VA_ARGS__, 22); break; \ + case 23: result = func_name(__VA_ARGS__, 23); break; \ + case 24: result = func_name(__VA_ARGS__, 24); break; \ + case 25: result = func_name(__VA_ARGS__, 25); break; \ + case 26: result = func_name(__VA_ARGS__, 26); break; \ + case 27: result = func_name(__VA_ARGS__, 27); break; \ + case 28: result = func_name(__VA_ARGS__, 28); break; \ + case 29: result = func_name(__VA_ARGS__, 29); break; \ + case 30: result = func_name(__VA_ARGS__, 30); break; \ + case 31: result = func_name(__VA_ARGS__, 31); break; \ + case 32: result = func_name(__VA_ARGS__, 32); break; \ + case 33: result = func_name(__VA_ARGS__, 33); break; \ + case 34: result = func_name(__VA_ARGS__, 34); break; \ + case 35: result = func_name(__VA_ARGS__, 35); break; \ + case 36: result = func_name(__VA_ARGS__, 36); break; \ + case 37: result = func_name(__VA_ARGS__, 37); break; \ + case 38: result = func_name(__VA_ARGS__, 38); break; \ + case 39: result = func_name(__VA_ARGS__, 39); break; \ + case 40: result = func_name(__VA_ARGS__, 40); break; \ + case 41: result = func_name(__VA_ARGS__, 41); break; \ + case 42: result = func_name(__VA_ARGS__, 42); break; \ + case 43: result = func_name(__VA_ARGS__, 43); break; \ + case 44: result = func_name(__VA_ARGS__, 44); break; \ + case 45: result = func_name(__VA_ARGS__, 45); break; \ + case 46: result = func_name(__VA_ARGS__, 46); break; \ + case 47: result = func_name(__VA_ARGS__, 47); break; \ + case 48: result = func_name(__VA_ARGS__, 48); break; \ + case 49: result = func_name(__VA_ARGS__, 49); break; \ + case 50: result = func_name(__VA_ARGS__, 50); break; \ + case 51: result = func_name(__VA_ARGS__, 51); break; \ + case 52: result = func_name(__VA_ARGS__, 52); break; \ + case 53: result = func_name(__VA_ARGS__, 53); break; \ + case 54: result = func_name(__VA_ARGS__, 54); break; \ + case 55: result = func_name(__VA_ARGS__, 55); break; \ + case 56: result = func_name(__VA_ARGS__, 56); break; \ + case 57: result = func_name(__VA_ARGS__, 57); break; \ + case 58: result = func_name(__VA_ARGS__, 58); break; \ + case 59: result = func_name(__VA_ARGS__, 59); break; \ + case 60: result = func_name(__VA_ARGS__, 60); break; \ + case 61: result = func_name(__VA_ARGS__, 61); break; \ + case 62: result = func_name(__VA_ARGS__, 62); break; \ + case 63: result = func_name(__VA_ARGS__, 63); break; \ + default: result = default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_2_NO_RESULT_(func_name, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: func_name(__VA_ARGS__, 0); break; \ + case 1: func_name(__VA_ARGS__, 1); break; \ + default: default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_4_NO_RESULT_(func_name, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: func_name(__VA_ARGS__, 0); break; \ + case 1: func_name(__VA_ARGS__, 1); break; \ + case 2: func_name(__VA_ARGS__, 2); break; \ + case 3: func_name(__VA_ARGS__, 3); break; \ + default: default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_8_NO_RESULT_(func_name, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: func_name(__VA_ARGS__, 0); break; \ + case 1: func_name(__VA_ARGS__, 1); break; \ + case 2: func_name(__VA_ARGS__, 2); break; \ + case 3: func_name(__VA_ARGS__, 3); break; \ + case 4: func_name(__VA_ARGS__, 4); break; \ + case 5: func_name(__VA_ARGS__, 5); break; \ + case 6: func_name(__VA_ARGS__, 6); break; \ + case 7: func_name(__VA_ARGS__, 7); break; \ + default: default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_16_NO_RESULT_(func_name, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: func_name(__VA_ARGS__, 0); break; \ + case 1: func_name(__VA_ARGS__, 1); break; \ + case 2: func_name(__VA_ARGS__, 2); break; \ + case 3: func_name(__VA_ARGS__, 3); break; \ + case 4: func_name(__VA_ARGS__, 4); break; \ + case 5: func_name(__VA_ARGS__, 5); break; \ + case 6: func_name(__VA_ARGS__, 6); break; \ + case 7: func_name(__VA_ARGS__, 7); break; \ + case 8: func_name(__VA_ARGS__, 8); break; \ + case 9: func_name(__VA_ARGS__, 9); break; \ + case 10: func_name(__VA_ARGS__, 10); break; \ + case 11: func_name(__VA_ARGS__, 11); break; \ + case 12: func_name(__VA_ARGS__, 12); break; \ + case 13: func_name(__VA_ARGS__, 13); break; \ + case 14: func_name(__VA_ARGS__, 14); break; \ + case 15: func_name(__VA_ARGS__, 15); break; \ + default: default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_32_NO_RESULT_(func_name, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: func_name(__VA_ARGS__, 0); break; \ + case 1: func_name(__VA_ARGS__, 1); break; \ + case 2: func_name(__VA_ARGS__, 2); break; \ + case 3: func_name(__VA_ARGS__, 3); break; \ + case 4: func_name(__VA_ARGS__, 4); break; \ + case 5: func_name(__VA_ARGS__, 5); break; \ + case 6: func_name(__VA_ARGS__, 6); break; \ + case 7: func_name(__VA_ARGS__, 7); break; \ + case 8: func_name(__VA_ARGS__, 8); break; \ + case 9: func_name(__VA_ARGS__, 9); break; \ + case 10: func_name(__VA_ARGS__, 10); break; \ + case 11: func_name(__VA_ARGS__, 11); break; \ + case 12: func_name(__VA_ARGS__, 12); break; \ + case 13: func_name(__VA_ARGS__, 13); break; \ + case 14: func_name(__VA_ARGS__, 14); break; \ + case 15: func_name(__VA_ARGS__, 15); break; \ + case 16: func_name(__VA_ARGS__, 16); break; \ + case 17: func_name(__VA_ARGS__, 17); break; \ + case 18: func_name(__VA_ARGS__, 18); break; \ + case 19: func_name(__VA_ARGS__, 19); break; \ + case 20: func_name(__VA_ARGS__, 20); break; \ + case 21: func_name(__VA_ARGS__, 21); break; \ + case 22: func_name(__VA_ARGS__, 22); break; \ + case 23: func_name(__VA_ARGS__, 23); break; \ + case 24: func_name(__VA_ARGS__, 24); break; \ + case 25: func_name(__VA_ARGS__, 25); break; \ + case 26: func_name(__VA_ARGS__, 26); break; \ + case 27: func_name(__VA_ARGS__, 27); break; \ + case 28: func_name(__VA_ARGS__, 28); break; \ + case 29: func_name(__VA_ARGS__, 29); break; \ + case 30: func_name(__VA_ARGS__, 30); break; \ + case 31: func_name(__VA_ARGS__, 31); break; \ + default: default_case; break; \ + } \ + } while (0) + +#define SIMDE_CONSTIFY_64_NO_RESULT_(func_name, default_case, imm, ...) \ + do { \ + switch(imm) { \ + case 0: func_name(__VA_ARGS__, 0); break; \ + case 1: func_name(__VA_ARGS__, 1); break; \ + case 2: func_name(__VA_ARGS__, 2); break; \ + case 3: func_name(__VA_ARGS__, 3); break; \ + case 4: func_name(__VA_ARGS__, 4); break; \ + case 5: func_name(__VA_ARGS__, 5); break; \ + case 6: func_name(__VA_ARGS__, 6); break; \ + case 7: func_name(__VA_ARGS__, 7); break; \ + case 8: func_name(__VA_ARGS__, 8); break; \ + case 9: func_name(__VA_ARGS__, 9); break; \ + case 10: func_name(__VA_ARGS__, 10); break; \ + case 11: func_name(__VA_ARGS__, 11); break; \ + case 12: func_name(__VA_ARGS__, 12); break; \ + case 13: func_name(__VA_ARGS__, 13); break; \ + case 14: func_name(__VA_ARGS__, 14); break; \ + case 15: func_name(__VA_ARGS__, 15); break; \ + case 16: func_name(__VA_ARGS__, 16); break; \ + case 17: func_name(__VA_ARGS__, 17); break; \ + case 18: func_name(__VA_ARGS__, 18); break; \ + case 19: func_name(__VA_ARGS__, 19); break; \ + case 20: func_name(__VA_ARGS__, 20); break; \ + case 21: func_name(__VA_ARGS__, 21); break; \ + case 22: func_name(__VA_ARGS__, 22); break; \ + case 23: func_name(__VA_ARGS__, 23); break; \ + case 24: func_name(__VA_ARGS__, 24); break; \ + case 25: func_name(__VA_ARGS__, 25); break; \ + case 26: func_name(__VA_ARGS__, 26); break; \ + case 27: func_name(__VA_ARGS__, 27); break; \ + case 28: func_name(__VA_ARGS__, 28); break; \ + case 29: func_name(__VA_ARGS__, 29); break; \ + case 30: func_name(__VA_ARGS__, 30); break; \ + case 31: func_name(__VA_ARGS__, 31); break; \ + case 32: func_name(__VA_ARGS__, 32); break; \ + case 33: func_name(__VA_ARGS__, 33); break; \ + case 34: func_name(__VA_ARGS__, 34); break; \ + case 35: func_name(__VA_ARGS__, 35); break; \ + case 36: func_name(__VA_ARGS__, 36); break; \ + case 37: func_name(__VA_ARGS__, 37); break; \ + case 38: func_name(__VA_ARGS__, 38); break; \ + case 39: func_name(__VA_ARGS__, 39); break; \ + case 40: func_name(__VA_ARGS__, 40); break; \ + case 41: func_name(__VA_ARGS__, 41); break; \ + case 42: func_name(__VA_ARGS__, 42); break; \ + case 43: func_name(__VA_ARGS__, 43); break; \ + case 44: func_name(__VA_ARGS__, 44); break; \ + case 45: func_name(__VA_ARGS__, 45); break; \ + case 46: func_name(__VA_ARGS__, 46); break; \ + case 47: func_name(__VA_ARGS__, 47); break; \ + case 48: func_name(__VA_ARGS__, 48); break; \ + case 49: func_name(__VA_ARGS__, 49); break; \ + case 50: func_name(__VA_ARGS__, 50); break; \ + case 51: func_name(__VA_ARGS__, 51); break; \ + case 52: func_name(__VA_ARGS__, 52); break; \ + case 53: func_name(__VA_ARGS__, 53); break; \ + case 54: func_name(__VA_ARGS__, 54); break; \ + case 55: func_name(__VA_ARGS__, 55); break; \ + case 56: func_name(__VA_ARGS__, 56); break; \ + case 57: func_name(__VA_ARGS__, 57); break; \ + case 58: func_name(__VA_ARGS__, 58); break; \ + case 59: func_name(__VA_ARGS__, 59); break; \ + case 60: func_name(__VA_ARGS__, 60); break; \ + case 61: func_name(__VA_ARGS__, 61); break; \ + case 62: func_name(__VA_ARGS__, 62); break; \ + case 63: func_name(__VA_ARGS__, 63); break; \ + default: default_case; break; \ + } \ + } while (0) + +HEDLEY_DIAGNOSTIC_POP + +#endif +/* :: End ../simde/simde/simde-constify.h :: */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/simde-align.h :: */ +/* Alignment + * Created by Evan Nemerson + * + * To the extent possible under law, the authors have waived all + * copyright and related or neighboring rights to this code. For + * details, see the Creative Commons Zero 1.0 Universal license at + * + * + * SPDX-License-Identifier: CC0-1.0 + * + ********************************************************************** + * + * This is portability layer which should help iron out some + * differences across various compilers, as well as various verisons of + * C and C++. + * + * It was originally developed for SIMD Everywhere + * (), but since its only + * dependency is Hedley (, also CC0) + * it can easily be used in other projects, so please feel free to do + * so. + * + * If you do use this in your project, please keep a link to SIMDe in + * your code to remind you where to report any bugs and/or check for + * updated versions. + * + * # API Overview + * + * The API has several parts, and most macros have a few variations. + * There are APIs for declaring aligned fields/variables, optimization + * hints, and run-time alignment checks. + * + * Briefly, macros ending with "_TO" take numeric values and are great + * when you know the value you would like to use. Macros ending with + * "_LIKE", on the other hand, accept a type and are used when you want + * to use the alignment of a type instead of hardcoding a value. + * + * Documentation for each section of the API is inline. + * + * True to form, MSVC is the main problem and imposes several + * limitations on the effectiveness of the APIs. Detailed descriptions + * of the limitations of each macro are inline, but in general: + * + * * On C11+ or C++11+ code written using this API will work. The + * ASSUME macros may or may not generate a hint to the compiler, but + * that is only an optimization issue and will not actually cause + * failures. + * * If you're using pretty much any compiler other than MSVC, + * everything should basically work as well as in C11/C++11. + */ + +#if !defined(SIMDE_ALIGN_H) +#define SIMDE_ALIGN_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ + +/* I know this seems a little silly, but some non-hosted compilers + * don't have stddef.h, so we try to accomodate them. */ +#if !defined(SIMDE_ALIGN_SIZE_T_) + #if defined(__SIZE_TYPE__) + #define SIMDE_ALIGN_SIZE_T_ __SIZE_TYPE__ + #elif defined(__SIZE_T_TYPE__) + #define SIMDE_ALIGN_SIZE_T_ __SIZE_TYPE__ + #elif defined(__cplusplus) + #include + #define SIMDE_ALIGN_SIZE_T_ size_t + #else + #include + #define SIMDE_ALIGN_SIZE_T_ size_t + #endif +#endif + +#if !defined(SIMDE_ALIGN_INTPTR_T_) + #if defined(__INTPTR_TYPE__) + #define SIMDE_ALIGN_INTPTR_T_ __INTPTR_TYPE__ + #elif defined(__PTRDIFF_TYPE__) + #define SIMDE_ALIGN_INTPTR_T_ __PTRDIFF_TYPE__ + #elif defined(__PTRDIFF_T_TYPE__) + #define SIMDE_ALIGN_INTPTR_T_ __PTRDIFF_T_TYPE__ + #elif defined(__cplusplus) + #include + #define SIMDE_ALIGN_INTPTR_T_ ptrdiff_t + #else + #include + #define SIMDE_ALIGN_INTPTR_T_ ptrdiff_t + #endif +#endif + +#if defined(SIMDE_ALIGN_DEBUG) + #if defined(__cplusplus) + #include + #else + #include + #endif +#endif + +/* SIMDE_ALIGN_OF(Type) + * + * The SIMDE_ALIGN_OF macro works like alignof, or _Alignof, or + * __alignof, or __alignof__, or __ALIGNOF__, depending on the compiler. + * It isn't defined everywhere (only when the compiler has some alignof- + * like feature we can use to implement it), but it should work in most + * modern compilers, as well as C11 and C++11. + * + * If we can't find an implementation for SIMDE_ALIGN_OF then the macro + * will not be defined, so if you can handle that situation sensibly + * you may need to sprinkle some ifdefs into your code. + */ +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (0 && HEDLEY_HAS_FEATURE(c_alignof)) + #define SIMDE_ALIGN_OF(Type) _Alignof(Type) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + (0 && HEDLEY_HAS_FEATURE(cxx_alignof)) + #define SIMDE_ALIGN_OF(Type) alignof(Type) +#elif \ + HEDLEY_GCC_VERSION_CHECK(2,95,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,24) || \ + HEDLEY_PGI_VERSION_CHECK(19,10,0) || \ + HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,2) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + defined(__IBM__ALIGNOF__) || \ + defined(__clang__) + #define SIMDE_ALIGN_OF(Type) __alignof__(Type) +#elif \ + HEDLEY_IAR_VERSION_CHECK(8,40,0) + #define SIMDE_ALIGN_OF(Type) __ALIGNOF__(Type) +#elif \ + HEDLEY_MSVC_VERSION_CHECK(19,0,0) + /* Probably goes back much further, but MS takes down their old docs. + * If you can verify that this works in earlier versions please let + * me know! */ + #define SIMDE_ALIGN_OF(Type) __alignof(Type) +#endif + +/* SIMDE_ALIGN_MAXIMUM: + * + * This is the maximum alignment that the compiler supports. You can + * define the value prior to including SIMDe if necessary, but in that + * case *please* submit an issue so we can add the platform to the + * detection code. + * + * Most compilers are okay with types which are aligned beyond what + * they think is the maximum, as long as the alignment is a power + * of two. Older versions of MSVC is the exception, so we need to cap + * the alignment requests at values that the implementation supports. + * + * XL C/C++ will accept values larger than 16 (which is the alignment + * of an AltiVec vector), but will not reliably align to the larger + * value, so so we cap the value at 16 there. + * + * If the compiler accepts any power-of-two value within reason then + * this macro should be left undefined, and the SIMDE_ALIGN_CAP + * macro will just return the value passed to it. */ +#if !defined(SIMDE_ALIGN_MAXIMUM) + #if defined(HEDLEY_MSVC_VERSION) + #if HEDLEY_MSVC_VERSION_CHECK(19, 16, 0) + // Visual studio 2017 and newer does not need a max + #else + #if defined(_M_IX86) || defined(_M_AMD64) + #if HEDLEY_MSVC_VERSION_CHECK(19,14,0) + #define SIMDE_ALIGN_PLATFORM_MAXIMUM 64 + #elif HEDLEY_MSVC_VERSION_CHECK(16,0,0) + /* VS 2010 is really a guess based on Wikipedia; if anyone can + * test with old VS versions I'd really appreciate it. */ + #define SIMDE_ALIGN_PLATFORM_MAXIMUM 32 + #else + #define SIMDE_ALIGN_PLATFORM_MAXIMUM 16 + #endif + #elif defined(_M_ARM) || defined(_M_ARM64) + #define SIMDE_ALIGN_PLATFORM_MAXIMUM 8 + #endif + #endif + #elif defined(HEDLEY_IBM_VERSION) + #define SIMDE_ALIGN_PLATFORM_MAXIMUM 16 + #endif +#endif + +/* You can mostly ignore these; they're intended for internal use. + * If you do need to use them please let me know; if they fulfill + * a common use case I'll probably drop the trailing underscore + * and make them part of the public API. */ +#if defined(SIMDE_ALIGN_PLATFORM_MAXIMUM) + #if SIMDE_ALIGN_PLATFORM_MAXIMUM >= 64 + #define SIMDE_ALIGN_64_ 64 + #define SIMDE_ALIGN_32_ 32 + #define SIMDE_ALIGN_16_ 16 + #define SIMDE_ALIGN_8_ 8 + #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 32 + #define SIMDE_ALIGN_64_ 32 + #define SIMDE_ALIGN_32_ 32 + #define SIMDE_ALIGN_16_ 16 + #define SIMDE_ALIGN_8_ 8 + #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 16 + #define SIMDE_ALIGN_64_ 16 + #define SIMDE_ALIGN_32_ 16 + #define SIMDE_ALIGN_16_ 16 + #define SIMDE_ALIGN_8_ 8 + #elif SIMDE_ALIGN_PLATFORM_MAXIMUM >= 8 + #define SIMDE_ALIGN_64_ 8 + #define SIMDE_ALIGN_32_ 8 + #define SIMDE_ALIGN_16_ 8 + #define SIMDE_ALIGN_8_ 8 + #else + #error Max alignment expected to be >= 8 + #endif +#else + #define SIMDE_ALIGN_64_ 64 + #define SIMDE_ALIGN_32_ 32 + #define SIMDE_ALIGN_16_ 16 + #define SIMDE_ALIGN_8_ 8 +#endif + +/** + * SIMDE_ALIGN_CAP(Alignment) + * + * Returns the minimum of Alignment or SIMDE_ALIGN_MAXIMUM. + */ +#if defined(SIMDE_ALIGN_MAXIMUM) + #define SIMDE_ALIGN_CAP(Alignment) (((Alignment) < (SIMDE_ALIGN_PLATFORM_MAXIMUM)) ? (Alignment) : (SIMDE_ALIGN_PLATFORM_MAXIMUM)) +#else + #define SIMDE_ALIGN_CAP(Alignment) (Alignment) +#endif + +/* SIMDE_ALIGN_TO(Alignment) + * + * SIMDE_ALIGN_TO is used to declare types or variables. It basically + * maps to the align attribute in most compilers, the align declspec + * in MSVC, or _Alignas/alignas in C11/C++11. + * + * Example: + * + * struct i32x4 { + * SIMDE_ALIGN_TO(16) int32_t values[4]; + * } + * + * Limitations: + * + * MSVC requires that the Alignment parameter be numeric; you can't do + * something like `SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(int))`. This is + * unfortunate because that's really how the LIKE macros are + * implemented, and I am not aware of a way to get anything like this + * to work without using the C11/C++11 keywords. + * + * It also means that we can't use SIMDE_ALIGN_CAP to limit the + * alignment to the value specified, which MSVC also requires, so on + * MSVC you should use the `SIMDE_ALIGN_TO_8/16/32/64` macros instead. + * They work like `SIMDE_ALIGN_TO(SIMDE_ALIGN_CAP(Alignment))` would, + * but should be safe to use on MSVC. + * + * All this is to say that, if you want your code to work on MSVC, you + * should use the SIMDE_ALIGN_TO_8/16/32/64 macros below instead of + * SIMDE_ALIGN_TO(8/16/32/64). + */ +#if \ + HEDLEY_HAS_ATTRIBUTE(aligned) || \ + HEDLEY_GCC_VERSION_CHECK(2,95,0) || \ + HEDLEY_CRAY_VERSION_CHECK(8,4,0) || \ + HEDLEY_IBM_VERSION_CHECK(11,1,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_PGI_VERSION_CHECK(19,4,0) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,24) || \ + HEDLEY_TI_ARMCL_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CL2000_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + HEDLEY_TI_CL430_VERSION_CHECK(16,9,0) || \ + HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,2) + #define SIMDE_ALIGN_TO(Alignment) __attribute__((__aligned__(SIMDE_ALIGN_CAP(Alignment)))) +#elif \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) + #define SIMDE_ALIGN_TO(Alignment) _Alignas(SIMDE_ALIGN_CAP(Alignment)) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) + #define SIMDE_ALIGN_TO(Alignment) alignas(SIMDE_ALIGN_CAP(Alignment)) +#elif \ + defined(HEDLEY_MSVC_VERSION) + #define SIMDE_ALIGN_TO(Alignment) __declspec(align(Alignment)) + /* Unfortunately MSVC can't handle __declspec(align(__alignof(Type))); + * the alignment passed to the declspec has to be an integer. */ + #define SIMDE_ALIGN_OF_UNUSABLE_FOR_LIKE +#endif +#define SIMDE_ALIGN_TO_64 SIMDE_ALIGN_TO(SIMDE_ALIGN_64_) +#define SIMDE_ALIGN_TO_32 SIMDE_ALIGN_TO(SIMDE_ALIGN_32_) +#define SIMDE_ALIGN_TO_16 SIMDE_ALIGN_TO(SIMDE_ALIGN_16_) +#define SIMDE_ALIGN_TO_8 SIMDE_ALIGN_TO(SIMDE_ALIGN_8_) + +/* SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) + * + * SIMDE_ALIGN_ASSUME_TO is semantically similar to C++20's + * std::assume_aligned, or __builtin_assume_aligned. It tells the + * compiler to assume that the provided pointer is aligned to an + * `Alignment`-byte boundary. + * + * If you define SIMDE_ALIGN_DEBUG prior to including this header then + * SIMDE_ALIGN_ASSUME_TO will turn into a runtime check. We don't + * integrate with NDEBUG in this header, but it may be a good idea to + * put something like this in your code: + * + * #if !defined(NDEBUG) + * #define SIMDE_ALIGN_DEBUG + * #endif + * #include <.../simde-align.h> + */ +#if \ + HEDLEY_HAS_BUILTIN(__builtin_assume_aligned) || \ + HEDLEY_GCC_VERSION_CHECK(4,7,0) + #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) \ + HEDLEY_REINTERPRET_CAST(__typeof__(Pointer), __builtin_assume_aligned(HEDLEY_CONST_CAST(void*, HEDLEY_REINTERPRET_CAST(const void*, Pointer)), Alignment)) +#elif HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) (__extension__ ({ \ + __typeof__(v) simde_assume_aligned_t_ = (Pointer); \ + __assume_aligned(simde_assume_aligned_t_, Alignment); \ + simde_assume_aligned_t_; \ + })) +#elif defined(__cplusplus) && (__cplusplus > 201703L) + #include + #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) std::assume_aligned(Pointer) +#else + #if defined(__cplusplus) + template HEDLEY_ALWAYS_INLINE static T* simde_align_assume_to_unchecked(T* ptr, const size_t alignment) + #else + HEDLEY_ALWAYS_INLINE static void* simde_align_assume_to_unchecked(void* ptr, const size_t alignment) + #endif + { + HEDLEY_ASSUME((HEDLEY_REINTERPRET_CAST(size_t, (ptr)) % SIMDE_ALIGN_CAP(alignment)) == 0); + return ptr; + } + #if defined(__cplusplus) + #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) simde_align_assume_to_unchecked((Pointer), (Alignment)) + #else + #define SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) simde_align_assume_to_unchecked(HEDLEY_CONST_CAST(void*, HEDLEY_REINTERPRET_CAST(const void*, Pointer)), (Alignment)) + #endif +#endif + +#if !defined(SIMDE_ALIGN_DEBUG) + #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) SIMDE_ALIGN_ASSUME_TO_UNCHECKED(Pointer, Alignment) +#else + #include + #if defined(__cplusplus) + template + static HEDLEY_ALWAYS_INLINE + T* + simde_align_assume_to_checked_uncapped(T* ptr, const size_t alignment, const char* file, int line, const char* ptrname) + #else + static HEDLEY_ALWAYS_INLINE + void* + simde_align_assume_to_checked_uncapped(void* ptr, const size_t alignment, const char* file, int line, const char* ptrname) + #endif + { + if (HEDLEY_UNLIKELY((HEDLEY_REINTERPRET_CAST(SIMDE_ALIGN_INTPTR_T_, (ptr)) % HEDLEY_STATIC_CAST(SIMDE_ALIGN_INTPTR_T_, SIMDE_ALIGN_CAP(alignment))) != 0)) { + fprintf(stderr, "%s:%d: alignment check failed for `%s' (%p %% %u == %u)\n", + file, line, ptrname, HEDLEY_REINTERPRET_CAST(const void*, ptr), + HEDLEY_STATIC_CAST(unsigned int, SIMDE_ALIGN_CAP(alignment)), + HEDLEY_STATIC_CAST(unsigned int, HEDLEY_REINTERPRET_CAST(SIMDE_ALIGN_INTPTR_T_, (ptr)) % HEDLEY_STATIC_CAST(SIMDE_ALIGN_INTPTR_T_, SIMDE_ALIGN_CAP(alignment)))); + } + + return ptr; + } + + #if defined(__cplusplus) + #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) simde_align_assume_to_checked_uncapped((Pointer), (Alignment), __FILE__, __LINE__, #Pointer) + #else + #define SIMDE_ALIGN_ASSUME_TO(Pointer, Alignment) simde_align_assume_to_checked_uncapped(HEDLEY_CONST_CAST(void*, HEDLEY_REINTERPRET_CAST(const void*, Pointer)), (Alignment), __FILE__, __LINE__, #Pointer) + #endif +#endif + +/* SIMDE_ALIGN_LIKE(Type) + * SIMDE_ALIGN_LIKE_#(Type) + * + * The SIMDE_ALIGN_LIKE macros are similar to the SIMDE_ALIGN_TO macros + * except instead of an integer they take a type; basically, it's just + * a more convenient way to do something like: + * + * SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(Type)) + * + * The versions with a numeric suffix will fall back on using a numeric + * value in the event we can't use SIMDE_ALIGN_OF(Type). This is + * mainly for MSVC, where __declspec(align()) can't handle anything + * other than hard-coded numeric values. + */ +#if defined(SIMDE_ALIGN_OF) && defined(SIMDE_ALIGN_TO) && !defined(SIMDE_ALIGN_OF_UNUSABLE_FOR_LIKE) + #define SIMDE_ALIGN_LIKE(Type) SIMDE_ALIGN_TO(SIMDE_ALIGN_OF(Type)) + #define SIMDE_ALIGN_LIKE_64(Type) SIMDE_ALIGN_LIKE(Type) + #define SIMDE_ALIGN_LIKE_32(Type) SIMDE_ALIGN_LIKE(Type) + #define SIMDE_ALIGN_LIKE_16(Type) SIMDE_ALIGN_LIKE(Type) + #define SIMDE_ALIGN_LIKE_8(Type) SIMDE_ALIGN_LIKE(Type) +#else + #define SIMDE_ALIGN_LIKE_64(Type) SIMDE_ALIGN_TO_64 + #define SIMDE_ALIGN_LIKE_32(Type) SIMDE_ALIGN_TO_32 + #define SIMDE_ALIGN_LIKE_16(Type) SIMDE_ALIGN_TO_16 + #define SIMDE_ALIGN_LIKE_8(Type) SIMDE_ALIGN_TO_8 +#endif + +/* SIMDE_ALIGN_ASSUME_LIKE(Pointer, Type) + * + * Tihs is similar to SIMDE_ALIGN_ASSUME_TO, except that it takes a + * type instead of a numeric value. */ +#if defined(SIMDE_ALIGN_OF) && defined(SIMDE_ALIGN_ASSUME_TO) + #define SIMDE_ALIGN_ASSUME_LIKE(Pointer, Type) SIMDE_ALIGN_ASSUME_TO(Pointer, SIMDE_ALIGN_OF(Type)) +#endif + +/* SIMDE_ALIGN_CAST(Type, Pointer) + * + * SIMDE_ALIGN_CAST is like C++'s reinterpret_cast, but it will try + * to silence warnings that some compilers may produce if you try + * to assign to a type with increased alignment requirements. + * + * Note that it does *not* actually attempt to tell the compiler that + * the pointer is aligned like the destination should be; that's the + * job of the next macro. This macro is necessary for stupid APIs + * like _mm_loadu_si128 where the input is a __m128i* but the function + * is specifically for data which isn't necessarily aligned to + * _Alignof(__m128i). + */ +#if HEDLEY_HAS_WARNING("-Wcast-align") || defined(__clang__) || HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define SIMDE_ALIGN_CAST(Type, Pointer) (__extension__({ \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("GCC diagnostic ignored \"-Wcast-align\"") \ + Type simde_r_ = HEDLEY_REINTERPRET_CAST(Type, Pointer); \ + HEDLEY_DIAGNOSTIC_POP \ + simde_r_; \ + })) +#else + #define SIMDE_ALIGN_CAST(Type, Pointer) HEDLEY_REINTERPRET_CAST(Type, Pointer) +#endif + +/* SIMDE_ALIGN_ASSUME_CAST(Type, Pointer) + * + * This is sort of like a combination of a reinterpret_cast and a + * SIMDE_ALIGN_ASSUME_LIKE. It uses SIMDE_ALIGN_ASSUME_LIKE to tell + * the compiler that the pointer is aligned like the specified type + * and casts the pointer to the specified type while suppressing any + * warnings from the compiler about casting to a type with greater + * alignment requirements. + */ +#define SIMDE_ALIGN_ASSUME_CAST(Type, Pointer) SIMDE_ALIGN_ASSUME_LIKE(SIMDE_ALIGN_CAST(Type, Pointer), Type) + +#endif /* !defined(SIMDE_ALIGN_H) */ +/* :: End ../simde/simde/simde-align.h :: */ + +/* In some situations, SIMDe has to make large performance sacrifices + * for small increases in how faithfully it reproduces an API, but + * only a relatively small number of users will actually need the API + * to be completely accurate. The SIMDE_FAST_* options can be used to + * disable these trade-offs. + * + * They can be enabled by passing -DSIMDE_FAST_MATH to the compiler, or + * the individual defines (e.g., -DSIMDE_FAST_NANS) if you only want to + * enable some optimizations. Using -ffast-math and/or + * -ffinite-math-only will also enable the relevant options. If you + * don't want that you can pass -DSIMDE_NO_FAST_* to disable them. */ + +/* Most programs avoid NaNs by never passing values which can result in + * a NaN; for example, if you only pass non-negative values to the sqrt + * functions, it won't generate a NaN. On some platforms, similar + * functions handle NaNs differently; for example, the _mm_min_ps SSE + * function will return 0.0 if you pass it (0.0, NaN), but the NEON + * vminq_f32 function will return NaN. Making them behave like one + * another is expensive; it requires generating a mask of all lanes + * with NaNs, then performing the operation (e.g., vminq_f32), then + * blending together the result with another vector using the mask. + * + * If you don't want SIMDe to worry about the differences between how + * NaNs are handled on the two platforms, define this (or pass + * -ffinite-math-only) */ +#if !defined(SIMDE_FAST_MATH) && !defined(SIMDE_NO_FAST_MATH) && defined(__FAST_MATH__) + #define SIMDE_FAST_MATH +#endif + +#if !defined(SIMDE_FAST_NANS) && !defined(SIMDE_NO_FAST_NANS) + #if defined(SIMDE_FAST_MATH) + #define SIMDE_FAST_NANS + #elif defined(__FINITE_MATH_ONLY__) + #if __FINITE_MATH_ONLY__ + #define SIMDE_FAST_NANS + #endif + #endif +#endif + +/* Many functions are defined as using the current rounding mode + * (i.e., the SIMD version of fegetround()) when converting to + * an integer. For example, _mm_cvtpd_epi32. Unfortunately, + * on some platforms (such as ARMv8+ where round-to-nearest is + * always used, regardless of the FPSCR register) this means we + * have to first query the current rounding mode, then choose + * the proper function (rounnd + , ceil, floor, etc.) */ +#if !defined(SIMDE_FAST_ROUND_MODE) && !defined(SIMDE_NO_FAST_ROUND_MODE) && defined(SIMDE_FAST_MATH) + #define SIMDE_FAST_ROUND_MODE +#endif + +/* This controls how ties are rounded. For example, does 10.5 round to + * 10 or 11? IEEE 754 specifies round-towards-even, but ARMv7 (for + * example) doesn't support it and it must be emulated (which is rather + * slow). If you're okay with just using the default for whatever arch + * you're on, you should definitely define this. + * + * Note that we don't use this macro to avoid correct implementations + * in functions which are explicitly about rounding (such as vrnd* on + * NEON, _mm_round_* on x86, etc.); it is only used for code where + * rounding is a component in another function, and even then it isn't + * usually a problem since such functions will use the current rounding + * mode. */ +#if !defined(SIMDE_FAST_ROUND_TIES) && !defined(SIMDE_NO_FAST_ROUND_TIES) && defined(SIMDE_FAST_MATH) + #define SIMDE_FAST_ROUND_TIES +#endif + +/* For functions which convert from one type to another (mostly from + * floating point to integer types), sometimes we need to do a range + * check and potentially return a different result if the value + * falls outside that range. Skipping this check can provide a + * performance boost, at the expense of faithfulness to the API we're + * emulating. */ +#if !defined(SIMDE_FAST_CONVERSION_RANGE) && !defined(SIMDE_NO_FAST_CONVERSION_RANGE) && defined(SIMDE_FAST_MATH) + #define SIMDE_FAST_CONVERSION_RANGE +#endif + +#if \ + HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define SIMDE_CHECK_CONSTANT_(expr) (__builtin_constant_p(expr)) +#elif defined(__cplusplus) && (__cplusplus > 201703L) + #include + #define SIMDE_CHECK_CONSTANT_(expr) (std::is_constant_evaluated()) +#endif + +#if !defined(SIMDE_NO_CHECK_IMMEDIATE_CONSTANT) + #if defined(SIMDE_CHECK_CONSTANT_) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(9,0,0) && \ + (!defined(__apple_build_version__) || ((__apple_build_version__ < 11000000) || (__apple_build_version__ >= 12000000))) + #define SIMDE_REQUIRE_CONSTANT(arg) HEDLEY_REQUIRE_MSG(SIMDE_CHECK_CONSTANT_(arg), "`" #arg "' must be constant") + #else + #define SIMDE_REQUIRE_CONSTANT(arg) + #endif +#else + #define SIMDE_REQUIRE_CONSTANT(arg) +#endif + +#define SIMDE_REQUIRE_RANGE(arg, min, max) \ + HEDLEY_REQUIRE_MSG((((arg) >= (min)) && ((arg) <= (max))), "'" #arg "' must be in [" #min ", " #max "]") + +#define SIMDE_REQUIRE_CONSTANT_RANGE(arg, min, max) \ + SIMDE_REQUIRE_CONSTANT(arg) \ + SIMDE_REQUIRE_RANGE(arg, min, max) + +/* A copy of HEDLEY_STATIC_ASSERT, except we don't define an empty + * fallback if we can't find an implementation; instead we have to + * check if SIMDE_STATIC_ASSERT is defined before using it. */ +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + HEDLEY_HAS_FEATURE(c_static_assert) || \ + HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define SIMDE_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + HEDLEY_MSVC_VERSION_CHECK(16,0,0) +# define SIMDE_STATIC_ASSERT(expr, message) HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#endif + +/* Statement exprs */ +#if \ + HEDLEY_GNUC_VERSION_CHECK(2,95,0) || \ + HEDLEY_TINYC_VERSION_CHECK(0,9,26) || \ + HEDLEY_INTEL_VERSION_CHECK(9,0,0) || \ + HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + HEDLEY_SUNPRO_VERSION_CHECK(5,12,0) || \ + HEDLEY_IBM_VERSION_CHECK(11,1,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define SIMDE_STATEMENT_EXPR_(expr) (__extension__ expr) +#endif + +#if defined(SIMDE_CHECK_CONSTANT_) && defined(SIMDE_STATIC_ASSERT) + #define SIMDE_ASSERT_CONSTANT_(v) SIMDE_STATIC_ASSERT(SIMDE_CHECK_CONSTANT_(v), #v " must be constant.") +#endif + +#if \ + (HEDLEY_HAS_ATTRIBUTE(may_alias) && !defined(HEDLEY_SUNPRO_VERSION)) || \ + HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) +# define SIMDE_MAY_ALIAS __attribute__((__may_alias__)) +#else +# define SIMDE_MAY_ALIAS +#endif + +/* Lots of compilers support GCC-style vector extensions, but many + don't support all the features. Define different macros depending + on support for + + * SIMDE_VECTOR - Declaring a vector. + * SIMDE_VECTOR_OPS - basic operations (binary and unary). + * SIMDE_VECTOR_NEGATE - negating a vector + * SIMDE_VECTOR_SCALAR - For binary operators, the second argument + can be a scalar, in which case the result is as if that scalar + had been broadcast to all lanes of a vector. + * SIMDE_VECTOR_SUBSCRIPT - Supports array subscript notation for + extracting/inserting a single element.= + + SIMDE_VECTOR can be assumed if any others are defined, the + others are independent. */ +#if !defined(SIMDE_NO_VECTOR) +# if \ + HEDLEY_GCC_VERSION_CHECK(4,8,0) +# define SIMDE_VECTOR(size) __attribute__((__vector_size__(size))) +# define SIMDE_VECTOR_OPS +# define SIMDE_VECTOR_NEGATE +# define SIMDE_VECTOR_SCALAR +# define SIMDE_VECTOR_SUBSCRIPT +# elif HEDLEY_INTEL_VERSION_CHECK(16,0,0) +# define SIMDE_VECTOR(size) __attribute__((__vector_size__(size))) +# define SIMDE_VECTOR_OPS +# define SIMDE_VECTOR_NEGATE +/* ICC only supports SIMDE_VECTOR_SCALAR for constants */ +# define SIMDE_VECTOR_SUBSCRIPT +# elif \ + HEDLEY_GCC_VERSION_CHECK(4,1,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define SIMDE_VECTOR(size) __attribute__((__vector_size__(size))) +# define SIMDE_VECTOR_OPS +# elif HEDLEY_SUNPRO_VERSION_CHECK(5,12,0) +# define SIMDE_VECTOR(size) __attribute__((__vector_size__(size))) +# elif HEDLEY_HAS_ATTRIBUTE(vector_size) +# define SIMDE_VECTOR(size) __attribute__((__vector_size__(size))) +# define SIMDE_VECTOR_OPS +# define SIMDE_VECTOR_NEGATE +# define SIMDE_VECTOR_SUBSCRIPT +# if SIMDE_DETECT_CLANG_VERSION_CHECK(5,0,0) +# define SIMDE_VECTOR_SCALAR +# endif +# endif + +/* GCC and clang have built-in functions to handle shuffling and + converting of vectors, but the implementations are slightly + different. This macro is just an abstraction over them. Note that + elem_size is in bits but vec_size is in bytes. */ +# if !defined(SIMDE_NO_SHUFFLE_VECTOR) && defined(SIMDE_VECTOR_SUBSCRIPT) + HEDLEY_DIAGNOSTIC_PUSH + /* We don't care about -Wvariadic-macros; all compilers that support + * shufflevector/shuffle support them. */ +# if HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# endif +# if HEDLEY_HAS_WARNING("-Wvariadic-macros") || HEDLEY_GCC_VERSION_CHECK(4,0,0) +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# endif + +# if HEDLEY_HAS_BUILTIN(__builtin_shufflevector) +# define SIMDE_SHUFFLE_VECTOR_(elem_size, vec_size, a, b, ...) __builtin_shufflevector(a, b, __VA_ARGS__) +# elif HEDLEY_GCC_HAS_BUILTIN(__builtin_shuffle,4,7,0) && !defined(__INTEL_COMPILER) +# define SIMDE_SHUFFLE_VECTOR_(elem_size, vec_size, a, b, ...) (__extension__ ({ \ + int##elem_size##_t SIMDE_VECTOR(vec_size) simde_shuffle_ = { __VA_ARGS__ }; \ + __builtin_shuffle(a, b, simde_shuffle_); \ + })) +# endif + HEDLEY_DIAGNOSTIC_POP +# endif + +/* TODO: this actually works on XL C/C++ without SIMDE_VECTOR_SUBSCRIPT + but the code needs to be refactored a bit to take advantage. */ +# if !defined(SIMDE_NO_CONVERT_VECTOR) && defined(SIMDE_VECTOR_SUBSCRIPT) +# if HEDLEY_HAS_BUILTIN(__builtin_convertvector) || HEDLEY_GCC_VERSION_CHECK(9,0,0) +# if HEDLEY_GCC_VERSION_CHECK(9,0,0) && !HEDLEY_GCC_VERSION_CHECK(9,3,0) + /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93557 */ +# define SIMDE_CONVERT_VECTOR_(to, from) ((to) = (__extension__({ \ + __typeof__(from) from_ = (from); \ + ((void) from_); \ + __builtin_convertvector(from_, __typeof__(to)); \ + }))) +# else +# define SIMDE_CONVERT_VECTOR_(to, from) ((to) = __builtin_convertvector((from), __typeof__(to))) +# endif +# endif +# endif +#endif + +/* Since we currently require SUBSCRIPT before using a vector in a + union, we define these as dependencies of SUBSCRIPT. They are + likely to disappear in the future, once SIMDe learns how to make + use of vectors without using the union members. Do not use them + in your code unless you're okay with it breaking when SIMDe + changes. */ +#if defined(SIMDE_VECTOR_SUBSCRIPT) +# if defined(SIMDE_VECTOR_OPS) +# define SIMDE_VECTOR_SUBSCRIPT_OPS +# endif +# if defined(SIMDE_VECTOR_SCALAR) +# define SIMDE_VECTOR_SUBSCRIPT_SCALAR +# endif +#endif + +#if !defined(SIMDE_DISABLE_OPENMP) + #if !defined(SIMDE_ENABLE_OPENMP) && ((defined(_OPENMP) && (_OPENMP >= 201307L)) || (defined(_OPENMP_SIMD) && (_OPENMP_SIMD >= 201307L))) || defined(HEDLEY_MCST_LCC_VERSION) + #define SIMDE_ENABLE_OPENMP + #endif +#endif + +#if !defined(SIMDE_ENABLE_CILKPLUS) && (defined(__cilk) || defined(HEDLEY_INTEL_VERSION)) +# define SIMDE_ENABLE_CILKPLUS +#endif + +#if defined(SIMDE_ENABLE_OPENMP) +# define SIMDE_VECTORIZE HEDLEY_PRAGMA(omp simd) +# define SIMDE_VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(omp simd safelen(l)) +# if defined(__clang__) +# define SIMDE_VECTORIZE_REDUCTION(r) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wsign-conversion\"") \ + HEDLEY_PRAGMA(omp simd reduction(r)) \ + HEDLEY_DIAGNOSTIC_POP +# else +# define SIMDE_VECTORIZE_REDUCTION(r) HEDLEY_PRAGMA(omp simd reduction(r)) +# endif +# define SIMDE_VECTORIZE_ALIGNED(a) HEDLEY_PRAGMA(omp simd aligned(a)) +#elif defined(SIMDE_ENABLE_CILKPLUS) +# define SIMDE_VECTORIZE HEDLEY_PRAGMA(simd) +# define SIMDE_VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(simd vectorlength(l)) +# define SIMDE_VECTORIZE_REDUCTION(r) HEDLEY_PRAGMA(simd reduction(r)) +# define SIMDE_VECTORIZE_ALIGNED(a) HEDLEY_PRAGMA(simd aligned(a)) +#elif defined(__clang__) && !defined(HEDLEY_IBM_VERSION) +# define SIMDE_VECTORIZE HEDLEY_PRAGMA(clang loop vectorize(enable)) +# define SIMDE_VECTORIZE_SAFELEN(l) HEDLEY_PRAGMA(clang loop vectorize_width(l)) +# define SIMDE_VECTORIZE_REDUCTION(r) SIMDE_VECTORIZE +# define SIMDE_VECTORIZE_ALIGNED(a) +#elif HEDLEY_GCC_VERSION_CHECK(4,9,0) +# define SIMDE_VECTORIZE HEDLEY_PRAGMA(GCC ivdep) +# define SIMDE_VECTORIZE_SAFELEN(l) SIMDE_VECTORIZE +# define SIMDE_VECTORIZE_REDUCTION(r) SIMDE_VECTORIZE +# define SIMDE_VECTORIZE_ALIGNED(a) +#elif HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define SIMDE_VECTORIZE HEDLEY_PRAGMA(_CRI ivdep) +# define SIMDE_VECTORIZE_SAFELEN(l) SIMDE_VECTORIZE +# define SIMDE_VECTORIZE_REDUCTION(r) SIMDE_VECTORIZE +# define SIMDE_VECTORIZE_ALIGNED(a) +#else +# define SIMDE_VECTORIZE +# define SIMDE_VECTORIZE_SAFELEN(l) +# define SIMDE_VECTORIZE_REDUCTION(r) +# define SIMDE_VECTORIZE_ALIGNED(a) +#endif + +#define SIMDE_MASK_NZ_(v, mask) (((v) & (mask)) | !((v) & (mask))) + +/* Intended for checking coverage, you should never use this in + production. */ +#if defined(SIMDE_NO_INLINE) +# define SIMDE_FUNCTION_ATTRIBUTES HEDLEY_NEVER_INLINE static +#else +# define SIMDE_FUNCTION_ATTRIBUTES HEDLEY_ALWAYS_INLINE static +#endif + +#if \ + HEDLEY_HAS_ATTRIBUTE(unused) || \ + HEDLEY_GCC_VERSION_CHECK(2,95,0) +# define SIMDE_FUNCTION_POSSIBLY_UNUSED_ __attribute__((__unused__)) +#else +# define SIMDE_FUNCTION_POSSIBLY_UNUSED_ +#endif + +#if HEDLEY_HAS_WARNING("-Wused-but-marked-unused") +# define SIMDE_DIAGNOSTIC_DISABLE_USED_BUT_MARKED_UNUSED _Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") +#else +# define SIMDE_DIAGNOSTIC_DISABLE_USED_BUT_MARKED_UNUSED +#endif + +#if defined(_MSC_VER) +# define SIMDE_BEGIN_DECLS_ HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(disable:4996 4204)) HEDLEY_BEGIN_C_DECLS +# define SIMDE_END_DECLS_ HEDLEY_DIAGNOSTIC_POP HEDLEY_END_C_DECLS +#else +# define SIMDE_BEGIN_DECLS_ \ + HEDLEY_DIAGNOSTIC_PUSH \ + SIMDE_DIAGNOSTIC_DISABLE_USED_BUT_MARKED_UNUSED \ + HEDLEY_BEGIN_C_DECLS +# define SIMDE_END_DECLS_ \ + HEDLEY_END_C_DECLS \ + HEDLEY_DIAGNOSTIC_POP +#endif + +#if defined(__SIZEOF_INT128__) +# define SIMDE_HAVE_INT128_ +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_PEDANTIC_ +typedef __int128 simde_int128; +typedef unsigned __int128 simde_uint128; +HEDLEY_DIAGNOSTIC_POP +#endif + +#if !defined(SIMDE_ENDIAN_LITTLE) +# define SIMDE_ENDIAN_LITTLE 1234 +#endif +#if !defined(SIMDE_ENDIAN_BIG) +# define SIMDE_ENDIAN_BIG 4321 +#endif + +#if !defined(SIMDE_ENDIAN_ORDER) +/* GCC (and compilers masquerading as GCC) define __BYTE_ORDER__. */ +# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +/* TI defines _BIG_ENDIAN or _LITTLE_ENDIAN */ +# elif defined(_BIG_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +# elif defined(_LITTLE_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +/* We know the endianness of some common architectures. Common + * architectures not listed (ARM, POWER, MIPS, etc.) here are + * bi-endian. */ +# elif defined(__amd64) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(__s390x__) || defined(__zarch__) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +/* Looks like we'll have to rely on the platform. If we're missing a + * platform, please let us know. */ +# elif defined(_WIN32) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(sun) || defined(__sun) /* Solaris */ +# include +# if defined(_LITTLE_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(_BIG_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +# endif +# elif defined(__APPLE__) +# include +# if defined(__LITTLE_ENDIAN__) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(__BIG_ENDIAN__) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +# endif +# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(BSD) +# include +# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +# endif +# elif defined(__linux__) || defined(__linux) || defined(__gnu_linux__) +# include +# if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_LITTLE +# elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) +# define SIMDE_ENDIAN_ORDER SIMDE_ENDIAN_BIG +# endif +# endif +#endif + +#if \ + HEDLEY_HAS_BUILTIN(__builtin_bswap64) || \ + HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define simde_bswap64(v) __builtin_bswap64(v) +#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define simde_bswap64(v) _byteswap_uint64(v) +#else + SIMDE_FUNCTION_ATTRIBUTES + uint64_t + simde_bswap64(uint64_t v) { + return + ((v & (((uint64_t) 0xff) << 56)) >> 56) | + ((v & (((uint64_t) 0xff) << 48)) >> 40) | + ((v & (((uint64_t) 0xff) << 40)) >> 24) | + ((v & (((uint64_t) 0xff) << 32)) >> 8) | + ((v & (((uint64_t) 0xff) << 24)) << 8) | + ((v & (((uint64_t) 0xff) << 16)) << 24) | + ((v & (((uint64_t) 0xff) << 8)) << 40) | + ((v & (((uint64_t) 0xff) )) << 56); + } +#endif + +#if !defined(SIMDE_ENDIAN_ORDER) +# error Unknown byte order; please file a bug +#else +# if SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE +# define simde_endian_bswap64_be(value) simde_bswap64(value) +# define simde_endian_bswap64_le(value) (value) +# elif SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_BIG +# define simde_endian_bswap64_be(value) (value) +# define simde_endian_bswap64_le(value) simde_bswap64(value) +# endif +#endif + +/* TODO: we should at least make an attempt to detect the correct + types for simde_float32/float64 instead of just assuming float and + double. */ + +#if !defined(SIMDE_FLOAT32_TYPE) +# define SIMDE_FLOAT32_TYPE float +# define SIMDE_FLOAT32_C(value) value##f +#else +# define SIMDE_FLOAT32_C(value) ((SIMDE_FLOAT32_TYPE) value) +#endif +typedef SIMDE_FLOAT32_TYPE simde_float32; + +#if !defined(SIMDE_FLOAT64_TYPE) +# define SIMDE_FLOAT64_TYPE double +# define SIMDE_FLOAT64_C(value) value +#else +# define SIMDE_FLOAT64_C(value) ((SIMDE_FLOAT64_TYPE) value) +#endif +typedef SIMDE_FLOAT64_TYPE simde_float64; + +#if defined(__cplusplus) + typedef bool simde_bool; +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + typedef _Bool simde_bool; +#elif defined(bool) + typedef bool simde_bool; +#else + #include + typedef bool simde_bool; +#endif + +#if HEDLEY_HAS_WARNING("-Wbad-function-cast") +# define SIMDE_CONVERT_FTOI(T,v) \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wbad-function-cast\"") \ + HEDLEY_STATIC_CAST(T, (v)) \ + HEDLEY_DIAGNOSTIC_POP +#else +# define SIMDE_CONVERT_FTOI(T,v) ((T) (v)) +#endif + +/* TODO: detect compilers which support this outside of C11 mode */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + #define SIMDE_CHECKED_REINTERPRET_CAST(to, from, value) _Generic((value), to: (value), default: (_Generic((value), from: ((to) (value))))) + #define SIMDE_CHECKED_STATIC_CAST(to, from, value) _Generic((value), to: (value), default: (_Generic((value), from: ((to) (value))))) +#else + #define SIMDE_CHECKED_REINTERPRET_CAST(to, from, value) HEDLEY_REINTERPRET_CAST(to, value) + #define SIMDE_CHECKED_STATIC_CAST(to, from, value) HEDLEY_STATIC_CAST(to, value) +#endif + +#if HEDLEY_HAS_WARNING("-Wfloat-equal") +# define SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") +#elif HEDLEY_GCC_VERSION_CHECK(3,0,0) +# define SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL _Pragma("GCC diagnostic ignored \"-Wfloat-equal\"") +#else +# define SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL +#endif + +/* Some functions can trade accuracy for speed. For those functions + you can control the trade-off using this macro. Possible values: + + 0: prefer speed + 1: reasonable trade-offs + 2: prefer accuracy */ +#if !defined(SIMDE_ACCURACY_PREFERENCE) +# define SIMDE_ACCURACY_PREFERENCE 1 +#endif + +#if defined(__STDC_HOSTED__) +# define SIMDE_STDC_HOSTED __STDC_HOSTED__ +#else +# if \ + defined(HEDLEY_PGI_VERSION) || \ + defined(HEDLEY_MSVC_VERSION) +# define SIMDE_STDC_HOSTED 1 +# else +# define SIMDE_STDC_HOSTED 0 +# endif +#endif + +/* Try to deal with environments without a standard library. */ +#if !defined(simde_memcpy) + #if HEDLEY_HAS_BUILTIN(__builtin_memcpy) + #define simde_memcpy(dest, src, n) __builtin_memcpy(dest, src, n) + #endif +#endif +#if !defined(simde_memset) + #if HEDLEY_HAS_BUILTIN(__builtin_memset) + #define simde_memset(s, c, n) __builtin_memset(s, c, n) + #endif +#endif +#if !defined(simde_memcmp) + #if HEDLEY_HAS_BUILTIN(__builtin_memcmp) + #define simde_memcmp(s1, s2, n) __builtin_memcmp(s1, s2, n) + #endif +#endif + +#if !defined(simde_memcpy) || !defined(simde_memset) || !defined(simde_memcmp) + #if !defined(SIMDE_NO_STRING_H) + #if defined(__has_include) + #if !__has_include() + #define SIMDE_NO_STRING_H + #endif + #elif (SIMDE_STDC_HOSTED == 0) + #define SIMDE_NO_STRING_H + #endif + #endif + + #if !defined(SIMDE_NO_STRING_H) + #include + #if !defined(simde_memcpy) + #define simde_memcpy(dest, src, n) memcpy(dest, src, n) + #endif + #if !defined(simde_memset) + #define simde_memset(s, c, n) memset(s, c, n) + #endif + #if !defined(simde_memcmp) + #define simde_memcmp(s1, s2, n) memcmp(s1, s2, n) + #endif + #else + /* These are meant to be portable, not fast. If you're hitting them you + * should think about providing your own (by defining the simde_memcpy + * macro prior to including any SIMDe files) or submitting a patch to + * SIMDe so we can detect your system-provided memcpy/memset, like by + * adding your compiler to the checks for __builtin_memcpy and/or + * __builtin_memset. */ + #if !defined(simde_memcpy) + SIMDE_FUNCTION_ATTRIBUTES + void + simde_memcpy_(void* dest, const void* src, size_t len) { + char* dest_ = HEDLEY_STATIC_CAST(char*, dest); + char* src_ = HEDLEY_STATIC_CAST(const char*, src); + for (size_t i = 0 ; i < len ; i++) { + dest_[i] = src_[i]; + } + } + #define simde_memcpy(dest, src, n) simde_memcpy_(dest, src, n) + #endif + + #if !defined(simde_memset) + SIMDE_FUNCTION_ATTRIBUTES + void + simde_memset_(void* s, int c, size_t len) { + char* s_ = HEDLEY_STATIC_CAST(char*, s); + char c_ = HEDLEY_STATIC_CAST(char, c); + for (size_t i = 0 ; i < len ; i++) { + s_[i] = c_[i]; + } + } + #define simde_memset(s, c, n) simde_memset_(s, c, n) + #endif + + #if !defined(simde_memcmp) + SIMDE_FUCTION_ATTRIBUTES + int + simde_memcmp_(const void *s1, const void *s2, size_t n) { + unsigned char* s1_ = HEDLEY_STATIC_CAST(unsigned char*, s1); + unsigned char* s2_ = HEDLEY_STATIC_CAST(unsigned char*, s2); + for (size_t i = 0 ; i < len ; i++) { + if (s1_[i] != s2_[i]) { + return (int) (s1_[i] - s2_[i]); + } + } + return 0; + } + #define simde_memcmp(s1, s2, n) simde_memcmp_(s1, s2, n) + #endif + #endif +#endif + +#if defined(FE_ALL_EXCEPT) + #define SIMDE_HAVE_FENV_H +#elif defined(__has_include) + #if __has_include() + #include + #define SIMDE_HAVE_FENV_H + #endif +#elif SIMDE_STDC_HOSTED == 1 + #include + #define SIMDE_HAVE_FENV_H +#endif + +#if defined(EXIT_FAILURE) + #define SIMDE_HAVE_STDLIB_H +#elif defined(__has_include) + #if __has_include() + #include + #define SIMDE_HAVE_STDLIB_H + #endif +#elif SIMDE_STDC_HOSTED == 1 + #include + #define SIMDE_HAVE_STDLIB_H +#endif + +#if defined(__has_include) +# if defined(__cplusplus) && (__cplusplus >= 201103L) && __has_include() +# include +# elif __has_include() +# include +# endif +# if __has_include() +# include +# endif +#elif SIMDE_STDC_HOSTED == 1 +# include +# include +#endif + +#define SIMDE_DEFINE_CONVERSION_FUNCTION_(Name, T_To, T_From) \ + static HEDLEY_ALWAYS_INLINE HEDLEY_CONST \ + T_To \ + Name (T_From value) { \ + T_To r; \ + simde_memcpy(&r, &value, sizeof(r)); \ + return r; \ + } + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/check.h :: */ +/* Check (assertions) + * Portable Snippets - https://gitub.com/nemequ/portable-snippets + * Created by Evan Nemerson + * + * To the extent possible under law, the authors have waived all + * copyright and related or neighboring rights to this code. For + * details, see the Creative Commons Zero 1.0 Universal license at + * https://creativecommons.org/publicdomain/zero/1.0/ + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(SIMDE_CHECK_H) +#define SIMDE_CHECK_H + +#if !defined(SIMDE_NDEBUG) && !defined(SIMDE_DEBUG) +# define SIMDE_NDEBUG 1 +#endif + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +#include + +#if !defined(_WIN32) +# define SIMDE_SIZE_MODIFIER "z" +# define SIMDE_CHAR_MODIFIER "hh" +# define SIMDE_SHORT_MODIFIER "h" +#else +# if defined(_M_X64) || defined(__amd64__) +# define SIMDE_SIZE_MODIFIER "I64" +# else +# define SIMDE_SIZE_MODIFIER "" +# endif +# define SIMDE_CHAR_MODIFIER "" +# define SIMDE_SHORT_MODIFIER "" +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1500) +# define SIMDE_PUSH_DISABLE_MSVC_C4127_ __pragma(warning(push)) __pragma(warning(disable:4127)) +# define SIMDE_POP_DISABLE_MSVC_C4127_ __pragma(warning(pop)) +#else +# define SIMDE_PUSH_DISABLE_MSVC_C4127_ +# define SIMDE_POP_DISABLE_MSVC_C4127_ +#endif + +#if !defined(simde_errorf) +# if defined(__has_include) +# if __has_include() +# include +# endif +# elif defined(SIMDE_STDC_HOSTED) +# if SIMDE_STDC_HOSTED == 1 +# include +# endif +# elif defined(__STDC_HOSTED__) +# if __STDC_HOSTETD__ == 1 +# include +# endif +# endif + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/debug-trap.h :: */ +/* Debugging assertions and traps + * Portable Snippets - https://gitub.com/nemequ/portable-snippets + * Created by Evan Nemerson + * + * To the extent possible under law, the authors have waived all + * copyright and related or neighboring rights to this code. For + * details, see the Creative Commons Zero 1.0 Universal license at + * https://creativecommons.org/publicdomain/zero/1.0/ + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(SIMDE_DEBUG_TRAP_H) +#define SIMDE_DEBUG_TRAP_H + +#if !defined(SIMDE_NDEBUG) && defined(NDEBUG) && !defined(SIMDE_DEBUG) +# define SIMDE_NDEBUG 1 +#endif + +#if defined(__has_builtin) && !defined(__ibmxl__) +# if __has_builtin(__builtin_debugtrap) +# define simde_trap() __builtin_debugtrap() +# elif __has_builtin(__debugbreak) +# define simde_trap() __debugbreak() +# endif +#endif +#if !defined(simde_trap) +# if defined(_MSC_VER) || defined(__INTEL_COMPILER) +# define simde_trap() __debugbreak() +# elif defined(__ARMCC_VERSION) +# define simde_trap() __breakpoint(42) +# elif defined(__ibmxl__) || defined(__xlC__) +# include +# define simde_trap() __trap(42) +# elif defined(__DMC__) && defined(_M_IX86) + static inline void simde_trap(void) { __asm int 3h; } +# elif defined(__i386__) || defined(__x86_64__) + static inline void simde_trap(void) { __asm__ __volatile__("int $03"); } +# elif defined(__thumb__) + static inline void simde_trap(void) { __asm__ __volatile__(".inst 0xde01"); } +# elif defined(__aarch64__) + static inline void simde_trap(void) { __asm__ __volatile__(".inst 0xd4200000"); } +# elif defined(__arm__) + static inline void simde_trap(void) { __asm__ __volatile__(".inst 0xe7f001f0"); } +# elif defined (__alpha__) && !defined(__osf__) + static inline void simde_trap(void) { __asm__ __volatile__("bpt"); } +# elif defined(_54_) + static inline void simde_trap(void) { __asm__ __volatile__("ESTOP"); } +# elif defined(_55_) + static inline void simde_trap(void) { __asm__ __volatile__(";\n .if (.MNEMONIC)\n ESTOP_1\n .else\n ESTOP_1()\n .endif\n NOP"); } +# elif defined(_64P_) + static inline void simde_trap(void) { __asm__ __volatile__("SWBP 0"); } +# elif defined(_6x_) + static inline void simde_trap(void) { __asm__ __volatile__("NOP\n .word 0x10000000"); } +# elif defined(__STDC_HOSTED__) && (__STDC_HOSTED__ == 0) && defined(__GNUC__) +# define simde_trap() __builtin_trap() +# else +# include +# if defined(SIGTRAP) +# define simde_trap() raise(SIGTRAP) +# else +# define simde_trap() raise(SIGABRT) +# endif +# endif +#endif + +#if defined(HEDLEY_LIKELY) +# define SIMDE_DBG_LIKELY(expr) HEDLEY_LIKELY(expr) +#elif defined(__GNUC__) && (__GNUC__ >= 3) +# define SIMDE_DBG_LIKELY(expr) __builtin_expect(!!(expr), 1) +#else +# define SIMDE_DBG_LIKELY(expr) (!!(expr)) +#endif + +#if !defined(SIMDE_NDEBUG) || (SIMDE_NDEBUG == 0) +# define simde_dbg_assert(expr) do { \ + if (!SIMDE_DBG_LIKELY(expr)) { \ + simde_trap(); \ + } \ + } while (0) +#else +# define simde_dbg_assert(expr) +#endif + +#endif /* !defined(SIMDE_DEBUG_TRAP_H) */ +/* :: End ../simde/simde/debug-trap.h :: */ + + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_VARIADIC_MACROS_ +# if defined(EOF) +# define simde_errorf(format, ...) (fprintf(stderr, format, __VA_ARGS__), abort()) +# else +# define simde_errorf(format, ...) (simde_trap()) +# endif + HEDLEY_DIAGNOSTIC_POP +#endif + +#define simde_error(msg) simde_errorf("%s", msg) + +#if defined(SIMDE_NDEBUG) || \ + (defined(__cplusplus) && (__cplusplus < 201103L)) || \ + (defined(__STDC__) && (__STDC__ < 199901L)) +# if defined(SIMDE_CHECK_FAIL_DEFINED) +# define simde_assert(expr) +# else +# if defined(HEDLEY_ASSUME) +# define simde_assert(expr) HEDLEY_ASSUME(expr) +# elif HEDLEY_GCC_VERSION_CHECK(4,5,0) +# define simde_assert(expr) ((void) (!!(expr) ? 1 : (__builtin_unreachable(), 1))) +# elif HEDLEY_MSVC_VERSION_CHECK(13,10,0) +# define simde_assert(expr) __assume(expr) +# else +# define simde_assert(expr) +# endif +# endif +# define simde_assert_true(expr) simde_assert(expr) +# define simde_assert_false(expr) simde_assert(!(expr)) +# define simde_assert_type_full(prefix, suffix, T, fmt, a, op, b) simde_assert(((a) op (b))) +# define simde_assert_double_equal(a, b, precision) +# define simde_assert_string_equal(a, b) +# define simde_assert_string_not_equal(a, b) +# define simde_assert_memory_equal(size, a, b) +# define simde_assert_memory_not_equal(size, a, b) +#else +# define simde_assert(expr) \ + do { \ + if (!HEDLEY_LIKELY(expr)) { \ + simde_error("assertion failed: " #expr "\n"); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_true(expr) \ + do { \ + if (!HEDLEY_LIKELY(expr)) { \ + simde_error("assertion failed: " #expr " is not true\n"); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_false(expr) \ + do { \ + if (!HEDLEY_LIKELY(!(expr))) { \ + simde_error("assertion failed: " #expr " is not false\n"); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_type_full(prefix, suffix, T, fmt, a, op, b) \ + do { \ + T simde_tmp_a_ = (a); \ + T simde_tmp_b_ = (b); \ + if (!(simde_tmp_a_ op simde_tmp_b_)) { \ + simde_errorf("assertion failed: %s %s %s (" prefix "%" fmt suffix " %s " prefix "%" fmt suffix ")\n", \ + #a, #op, #b, simde_tmp_a_, #op, simde_tmp_b_); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_double_equal(a, b, precision) \ + do { \ + const double simde_tmp_a_ = (a); \ + const double simde_tmp_b_ = (b); \ + const double simde_tmp_diff_ = ((simde_tmp_a_ - simde_tmp_b_) < 0) ? \ + -(simde_tmp_a_ - simde_tmp_b_) : \ + (simde_tmp_a_ - simde_tmp_b_); \ + if (HEDLEY_UNLIKELY(simde_tmp_diff_ > 1e-##precision)) { \ + simde_errorf("assertion failed: %s == %s (%0." #precision "g == %0." #precision "g)\n", \ + #a, #b, simde_tmp_a_, simde_tmp_b_); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# include +# define simde_assert_string_equal(a, b) \ + do { \ + const char* simde_tmp_a_ = a; \ + const char* simde_tmp_b_ = b; \ + if (HEDLEY_UNLIKELY(strcmp(simde_tmp_a_, simde_tmp_b_) != 0)) { \ + simde_errorf("assertion failed: string %s == %s (\"%s\" == \"%s\")\n", \ + #a, #b, simde_tmp_a_, simde_tmp_b_); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_string_not_equal(a, b) \ + do { \ + const char* simde_tmp_a_ = a; \ + const char* simde_tmp_b_ = b; \ + if (HEDLEY_UNLIKELY(strcmp(simde_tmp_a_, simde_tmp_b_) == 0)) { \ + simde_errorf("assertion failed: string %s != %s (\"%s\" == \"%s\")\n", \ + #a, #b, simde_tmp_a_, simde_tmp_b_); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_memory_equal(size, a, b) \ + do { \ + const unsigned char* simde_tmp_a_ = (const unsigned char*) (a); \ + const unsigned char* simde_tmp_b_ = (const unsigned char*) (b); \ + const size_t simde_tmp_size_ = (size); \ + if (HEDLEY_UNLIKELY(memcmp(simde_tmp_a_, simde_tmp_b_, simde_tmp_size_)) != 0) { \ + size_t simde_tmp_pos_; \ + for (simde_tmp_pos_ = 0 ; simde_tmp_pos_ < simde_tmp_size_ ; simde_tmp_pos_++) { \ + if (simde_tmp_a_[simde_tmp_pos_] != simde_tmp_b_[simde_tmp_pos_]) { \ + simde_errorf("assertion failed: memory %s == %s, at offset %" SIMDE_SIZE_MODIFIER "u\n", \ + #a, #b, simde_tmp_pos_); \ + break; \ + } \ + } \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ + +# define simde_assert_memory_not_equal(size, a, b) \ + do { \ + const unsigned char* simde_tmp_a_ = (const unsigned char*) (a); \ + const unsigned char* simde_tmp_b_ = (const unsigned char*) (b); \ + const size_t simde_tmp_size_ = (size); \ + if (HEDLEY_UNLIKELY(memcmp(simde_tmp_a_, simde_tmp_b_, simde_tmp_size_)) == 0) { \ + simde_errorf("assertion failed: memory %s != %s (%" SIMDE_SIZE_MODIFIER "u bytes)\n", \ + #a, #b, simde_tmp_size_); \ + } \ + SIMDE_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) \ + SIMDE_POP_DISABLE_MSVC_C4127_ +#endif + +#define simde_assert_type(T, fmt, a, op, b) \ + simde_assert_type_full("", "", T, fmt, a, op, b) + +#define simde_assert_char(a, op, b) \ + simde_assert_type_full("'\\x", "'", char, "02" SIMDE_CHAR_MODIFIER "x", a, op, b) +#define simde_assert_uchar(a, op, b) \ + simde_assert_type_full("'\\x", "'", unsigned char, "02" SIMDE_CHAR_MODIFIER "x", a, op, b) +#define simde_assert_short(a, op, b) \ + simde_assert_type(short, SIMDE_SHORT_MODIFIER "d", a, op, b) +#define simde_assert_ushort(a, op, b) \ + simde_assert_type(unsigned short, SIMDE_SHORT_MODIFIER "u", a, op, b) +#define simde_assert_int(a, op, b) \ + simde_assert_type(int, "d", a, op, b) +#define simde_assert_uint(a, op, b) \ + simde_assert_type(unsigned int, "u", a, op, b) +#define simde_assert_long(a, op, b) \ + simde_assert_type(long int, "ld", a, op, b) +#define simde_assert_ulong(a, op, b) \ + simde_assert_type(unsigned long int, "lu", a, op, b) +#define simde_assert_llong(a, op, b) \ + simde_assert_type(long long int, "lld", a, op, b) +#define simde_assert_ullong(a, op, b) \ + simde_assert_type(unsigned long long int, "llu", a, op, b) + +#define simde_assert_size(a, op, b) \ + simde_assert_type(size_t, SIMDE_SIZE_MODIFIER "u", a, op, b) + +#define simde_assert_float(a, op, b) \ + simde_assert_type(float, "f", a, op, b) +#define simde_assert_double(a, op, b) \ + simde_assert_type(double, "g", a, op, b) +#define simde_assert_ptr(a, op, b) \ + simde_assert_type(const void*, "p", a, op, b) + +#define simde_assert_int8(a, op, b) \ + simde_assert_type(int8_t, PRIi8, a, op, b) +#define simde_assert_uint8(a, op, b) \ + simde_assert_type(uint8_t, PRIu8, a, op, b) +#define simde_assert_int16(a, op, b) \ + simde_assert_type(int16_t, PRIi16, a, op, b) +#define simde_assert_uint16(a, op, b) \ + simde_assert_type(uint16_t, PRIu16, a, op, b) +#define simde_assert_int32(a, op, b) \ + simde_assert_type(int32_t, PRIi32, a, op, b) +#define simde_assert_uint32(a, op, b) \ + simde_assert_type(uint32_t, PRIu32, a, op, b) +#define simde_assert_int64(a, op, b) \ + simde_assert_type(int64_t, PRIi64, a, op, b) +#define simde_assert_uint64(a, op, b) \ + simde_assert_type(uint64_t, PRIu64, a, op, b) + +#define simde_assert_ptr_equal(a, b) \ + simde_assert_ptr(a, ==, b) +#define simde_assert_ptr_not_equal(a, b) \ + simde_assert_ptr(a, !=, b) +#define simde_assert_null(ptr) \ + simde_assert_ptr(ptr, ==, NULL) +#define simde_assert_not_null(ptr) \ + simde_assert_ptr(ptr, !=, NULL) +#define simde_assert_ptr_null(ptr) \ + simde_assert_ptr(ptr, ==, NULL) +#define simde_assert_ptr_not_null(ptr) \ + simde_assert_ptr(ptr, !=, NULL) + +#endif /* !defined(SIMDE_CHECK_H) */ +/* :: End ../simde/simde/check.h :: */ + +/* GCC/clang have a bunch of functionality in builtins which we would + * like to access, but the suffixes indicate whether the operate on + * int, long, or long long, not fixed width types (e.g., int32_t). + * we use these macros to attempt to map from fixed-width to the + * names GCC uses. Note that you should still cast the input(s) and + * return values (to/from SIMDE_BUILTIN_TYPE_*_) since often even if + * types are the same size they may not be compatible according to the + * compiler. For example, on x86 long and long lonsg are generally + * both 64 bits, but platforms vary on whether an int64_t is mapped + * to a long or long long. */ + +#include + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_CPP98_COMPAT_PEDANTIC_ + +#if (INT8_MAX == INT_MAX) && (INT8_MIN == INT_MIN) + #define SIMDE_BUILTIN_SUFFIX_8_ + #define SIMDE_BUILTIN_TYPE_8_ int +#elif (INT8_MAX == LONG_MAX) && (INT8_MIN == LONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_8_ l + #define SIMDE_BUILTIN_TYPE_8_ long +#elif (INT8_MAX == LLONG_MAX) && (INT8_MIN == LLONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_8_ ll + #define SIMDE_BUILTIN_TYPE_8_ long long +#endif + +#if (INT16_MAX == INT_MAX) && (INT16_MIN == INT_MIN) + #define SIMDE_BUILTIN_SUFFIX_16_ + #define SIMDE_BUILTIN_TYPE_16_ int +#elif (INT16_MAX == LONG_MAX) && (INT16_MIN == LONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_16_ l + #define SIMDE_BUILTIN_TYPE_16_ long +#elif (INT16_MAX == LLONG_MAX) && (INT16_MIN == LLONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_16_ ll + #define SIMDE_BUILTIN_TYPE_16_ long long +#endif + +#if (INT32_MAX == INT_MAX) && (INT32_MIN == INT_MIN) + #define SIMDE_BUILTIN_SUFFIX_32_ + #define SIMDE_BUILTIN_TYPE_32_ int +#elif (INT32_MAX == LONG_MAX) && (INT32_MIN == LONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_32_ l + #define SIMDE_BUILTIN_TYPE_32_ long +#elif (INT32_MAX == LLONG_MAX) && (INT32_MIN == LLONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_32_ ll + #define SIMDE_BUILTIN_TYPE_32_ long long +#endif + +#if (INT64_MAX == INT_MAX) && (INT64_MIN == INT_MIN) + #define SIMDE_BUILTIN_SUFFIX_64_ + #define SIMDE_BUILTIN_TYPE_64_ int +#elif (INT64_MAX == LONG_MAX) && (INT64_MIN == LONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_64_ l + #define SIMDE_BUILTIN_TYPE_64_ long +#elif (INT64_MAX == LLONG_MAX) && (INT64_MIN == LLONG_MIN) + #define SIMDE_BUILTIN_SUFFIX_64_ ll + #define SIMDE_BUILTIN_TYPE_64_ long long +#endif + +#if defined(SIMDE_BUILTIN_SUFFIX_8_) + #define SIMDE_BUILTIN_8_(name) HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_8_) + #define SIMDE_BUILTIN_HAS_8_(name) HEDLEY_HAS_BUILTIN(HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_8_)) +#else + #define SIMDE_BUILTIN_HAS_8_(name) 0 +#endif +#if defined(SIMDE_BUILTIN_SUFFIX_16_) + #define SIMDE_BUILTIN_16_(name) HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_16_) + #define SIMDE_BUILTIN_HAS_16_(name) HEDLEY_HAS_BUILTIN(HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_16_)) +#else + #define SIMDE_BUILTIN_HAS_16_(name) 0 +#endif +#if defined(SIMDE_BUILTIN_SUFFIX_32_) + #define SIMDE_BUILTIN_32_(name) HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_32_) + #define SIMDE_BUILTIN_HAS_32_(name) HEDLEY_HAS_BUILTIN(HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_32_)) +#else + #define SIMDE_BUILTIN_HAS_32_(name) 0 +#endif +#if defined(SIMDE_BUILTIN_SUFFIX_64_) + #define SIMDE_BUILTIN_64_(name) HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_64_) + #define SIMDE_BUILTIN_HAS_64_(name) HEDLEY_HAS_BUILTIN(HEDLEY_CONCAT3(__builtin_, name, SIMDE_BUILTIN_SUFFIX_64_)) +#else + #define SIMDE_BUILTIN_HAS_64_(name) 0 +#endif + +HEDLEY_DIAGNOSTIC_POP + +/* Sometimes we run into problems with specific versions of compilers + which make the native versions unusable for us. Often this is due + to missing functions, sometimes buggy implementations, etc. These + macros are how we check for specific bugs. As they are fixed we'll + start only defining them for problematic compiler versions. */ + +#if !defined(SIMDE_IGNORE_COMPILER_BUGS) +# if defined(HEDLEY_GCC_VERSION) +# if !HEDLEY_GCC_VERSION_CHECK(4,9,0) +# define SIMDE_BUG_GCC_REV_208793 +# endif +# if !HEDLEY_GCC_VERSION_CHECK(5,0,0) +# define SIMDE_BUG_GCC_BAD_MM_SRA_EPI32 /* TODO: find relevant bug or commit */ +# endif +# if !HEDLEY_GCC_VERSION_CHECK(6,0,0) +# define SIMDE_BUG_GCC_SIZEOF_IMMEDIATE +# endif +# if !HEDLEY_GCC_VERSION_CHECK(4,6,0) +# define SIMDE_BUG_GCC_BAD_MM_EXTRACT_EPI8 /* TODO: find relevant bug or commit */ +# endif +# if !HEDLEY_GCC_VERSION_CHECK(8,0,0) +# define SIMDE_BUG_GCC_REV_247851 +# endif +# if !HEDLEY_GCC_VERSION_CHECK(10,0,0) +# define SIMDE_BUG_GCC_REV_274313 +# define SIMDE_BUG_GCC_91341 +# endif +# if !HEDLEY_GCC_VERSION_CHECK(9,0,0) && defined(SIMDE_ARCH_AARCH64) +# define SIMDE_BUG_GCC_ARM_SHIFT_SCALAR +# endif +# if !HEDLEY_GCC_VERSION_CHECK(9,0,0) && defined(SIMDE_ARCH_AARCH64) +# define SIMDE_BUG_GCC_BAD_VEXT_REV32 +# endif +# if defined(SIMDE_ARCH_X86) && !defined(SIMDE_ARCH_AMD64) +# define SIMDE_BUG_GCC_94482 +# endif +# if (defined(SIMDE_ARCH_X86) && !defined(SIMDE_ARCH_AMD64)) || defined(SIMDE_ARCH_ZARCH) +# define SIMDE_BUG_GCC_53784 +# endif +# if defined(SIMDE_ARCH_X86) || defined(SIMDE_ARCH_AMD64) +# if HEDLEY_GCC_VERSION_CHECK(4,3,0) /* -Wsign-conversion */ +# define SIMDE_BUG_GCC_95144 +# endif +# if !HEDLEY_GCC_VERSION_CHECK(11,0,0) +# define SIMDE_BUG_GCC_95483 +# endif +# define SIMDE_BUG_GCC_98521 +# endif +# if !HEDLEY_GCC_VERSION_CHECK(9,4,0) && defined(SIMDE_ARCH_AARCH64) +# define SIMDE_BUG_GCC_94488 +# endif +# if !HEDLEY_GCC_VERSION_CHECK(9,1,0) && defined(SIMDE_ARCH_AARCH64) +# define SIMDE_BUG_GCC_REV_264019 +# endif +# if defined(SIMDE_ARCH_ARM) +# define SIMDE_BUG_GCC_95399 +# define SIMDE_BUG_GCC_95471 +# elif defined(SIMDE_ARCH_POWER) +# define SIMDE_BUG_GCC_95227 +# define SIMDE_BUG_GCC_95782 +# elif defined(SIMDE_ARCH_X86) || defined(SIMDE_ARCH_AMD64) +# if !HEDLEY_GCC_VERSION_CHECK(10,2,0) && !defined(__OPTIMIZE__) +# define SIMDE_BUG_GCC_96174 +# endif +# elif defined(SIMDE_ARCH_ZARCH) +# if !HEDLEY_GCC_VERSION_CHECK(9,0,0) +# define SIMDE_BUG_GCC_95782 +# endif +# endif +# define SIMDE_BUG_GCC_95399 +# elif defined(__clang__) +# if defined(SIMDE_ARCH_AARCH64) +# define SIMDE_BUG_CLANG_45541 +# define SIMDE_BUG_CLANG_46844 +# define SIMDE_BUG_CLANG_48257 +# if SIMDE_DETECT_CLANG_VERSION_CHECK(10,0,0) && SIMDE_DETECT_CLANG_VERSION_NOT(11,0,0) +# define SIMDE_BUG_CLANG_BAD_VI64_OPS +# endif +# if SIMDE_DETECT_CLANG_VERSION_NOT(9,0,0) +# define SIMDE_BUG_CLANG_GIT_4EC445B8 +# define SIMDE_BUG_CLANG_REV_365298 /* 0464e07c8f6e3310c28eb210a4513bc2243c2a7e */ +# endif +# endif +# if defined(SIMDE_ARCH_ARM) +# if !SIMDE_DETECT_CLANG_VERSION_CHECK(11,0,0) +# define SIMDE_BUG_CLANG_BAD_VGET_SET_LANE_TYPES +# endif +# endif +# if defined(SIMDE_ARCH_POWER) +# define SIMDE_BUG_CLANG_46770 +# endif +# if defined(_ARCH_PWR9) && !SIMDE_DETECT_CLANG_VERSION_CHECK(12,0,0) && !defined(__OPTIMIZE__) +# define SIMDE_BUG_CLANG_POWER9_16x4_BAD_SHIFT +# endif +# if defined(SIMDE_ARCH_X86) || defined(SIMDE_ARCH_AMD64) +# if SIMDE_DETECT_CLANG_VERSION_NOT(5,0,0) +# define SIMDE_BUG_CLANG_REV_298042 /* 6afc436a7817a52e78ae7bcdc3faafd460124cac */ +# endif +# if SIMDE_DETECT_CLANG_VERSION_NOT(3,7,0) +# define SIMDE_BUG_CLANG_REV_234560 /* b929ad7b1726a32650a8051f69a747fb6836c540 */ +# endif +# if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) && SIMDE_DETECT_CLANG_VERSION_NOT(5,0,0) +# define SIMDE_BUG_CLANG_BAD_MADD +# endif +# if SIMDE_DETECT_CLANG_VERSION_CHECK(4,0,0) && SIMDE_DETECT_CLANG_VERSION_NOT(5,0,0) +# define SIMDE_BUG_CLANG_REV_299346 /* ac9959eb533a58482ea4da6c4db1e635a98de384 */ +# endif +# if SIMDE_DETECT_CLANG_VERSION_NOT(8,0,0) +# define SIMDE_BUG_CLANG_REV_344862 /* eae26bf73715994c2bd145f9b6dc3836aa4ffd4f */ +# endif +# if HEDLEY_HAS_WARNING("-Wsign-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(11,0,0) +# define SIMDE_BUG_CLANG_45931 +# endif +# if HEDLEY_HAS_WARNING("-Wvector-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(11,0,0) +# define SIMDE_BUG_CLANG_44589 +# endif +# define SIMDE_BUG_CLANG_48673 +# endif +# define SIMDE_BUG_CLANG_45959 +# elif defined(HEDLEY_MSVC_VERSION) +# if defined(SIMDE_ARCH_X86) +# define SIMDE_BUG_MSVC_ROUND_EXTRACT +# endif +# elif defined(HEDLEY_INTEL_VERSION) +# define SIMDE_BUG_INTEL_857088 +# elif defined(HEDLEY_MCST_LCC_VERSION) +# define SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS +# endif +#endif + +/* GCC and Clang both have the same issue: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95144 + * https://bugs.llvm.org/show_bug.cgi?id=45931 + * This is just an easy way to work around it. + */ +#if \ + (HEDLEY_HAS_WARNING("-Wsign-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(11,0,0)) || \ + HEDLEY_GCC_VERSION_CHECK(4,3,0) +# define SIMDE_BUG_IGNORE_SIGN_CONVERSION(expr) (__extension__ ({ \ + HEDLEY_DIAGNOSTIC_PUSH \ + HEDLEY_DIAGNOSTIC_POP \ + _Pragma("GCC diagnostic ignored \"-Wsign-conversion\"") \ + __typeof__(expr) simde_bug_ignore_sign_conversion_v_= (expr); \ + HEDLEY_DIAGNOSTIC_PUSH \ + simde_bug_ignore_sign_conversion_v_; \ + })) +#else +# define SIMDE_BUG_IGNORE_SIGN_CONVERSION(expr) (expr) +#endif + +/* Usually the shift count is signed (for example, NEON or SSE). + * OTOH, unsigned is good for PPC (vec_srl uses unsigned), and the only option for E2K. + * Further info: https://github.com/simd-everywhere/simde/pull/700 + */ +#if defined(SIMDE_ARCH_E2K) || defined(SIMDE_ARCH_POWER) + #define SIMDE_CAST_VECTOR_SHIFT_COUNT(width, value) HEDLEY_STATIC_CAST(uint##width##_t, (value)) +#else + #define SIMDE_CAST_VECTOR_SHIFT_COUNT(width, value) HEDLEY_STATIC_CAST(int##width##_t, (value)) +#endif + +#endif /* !defined(SIMDE_COMMON_H) */ +/* :: End ../simde/simde/simde-common.h :: */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS + +#if defined(SIMDE_X86_MMX_NATIVE) + #define SIMDE_X86_MMX_USE_NATIVE_TYPE +#elif defined(SIMDE_X86_SSE_NATIVE) + #define SIMDE_X86_MMX_USE_NATIVE_TYPE +#endif + +#if defined(SIMDE_X86_MMX_USE_NATIVE_TYPE) + #include +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #include +#elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + #include +#endif + +#include +#include + +SIMDE_BEGIN_DECLS_ + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_8 int8_t i8 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 int16_t i16 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 int32_t i32 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 int64_t i64 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 uint8_t u8 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 uint16_t u16 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 uint32_t u32 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 uint64_t u64 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 simde_float32 f32 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 int_fast32_t i32f SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_8 uint_fast32_t u32f SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_8 int8_t i8[8]; + SIMDE_ALIGN_TO_8 int16_t i16[4]; + SIMDE_ALIGN_TO_8 int32_t i32[2]; + SIMDE_ALIGN_TO_8 int64_t i64[1]; + SIMDE_ALIGN_TO_8 uint8_t u8[8]; + SIMDE_ALIGN_TO_8 uint16_t u16[4]; + SIMDE_ALIGN_TO_8 uint32_t u32[2]; + SIMDE_ALIGN_TO_8 uint64_t u64[1]; + SIMDE_ALIGN_TO_8 simde_float32 f32[2]; + SIMDE_ALIGN_TO_8 int_fast32_t i32f[8 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_8 uint_fast32_t u32f[8 / sizeof(uint_fast32_t)]; + #endif + + #if defined(SIMDE_X86_MMX_USE_NATIVE_TYPE) + __m64 n; + #endif + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int8x8_t neon_i8; + int16x4_t neon_i16; + int32x2_t neon_i32; + int64x1_t neon_i64; + uint8x8_t neon_u8; + uint16x4_t neon_u16; + uint32x2_t neon_u32; + uint64x1_t neon_u64; + float32x2_t neon_f32; + #endif + #if defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + int8x8_t mmi_i8; + int16x4_t mmi_i16; + int32x2_t mmi_i32; + int64_t mmi_i64; + uint8x8_t mmi_u8; + uint16x4_t mmi_u16; + uint32x2_t mmi_u32; + uint64_t mmi_u64; + #endif +} simde__m64_private; + +#if defined(SIMDE_X86_MMX_USE_NATIVE_TYPE) + typedef __m64 simde__m64; +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + typedef int32x2_t simde__m64; +#elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + typedef int32x2_t simde__m64; +#elif defined(SIMDE_VECTOR_SUBSCRIPT) + typedef int32_t simde__m64 SIMDE_ALIGN_TO_8 SIMDE_VECTOR(8) SIMDE_MAY_ALIAS; +#else + typedef simde__m64_private simde__m64; +#endif + +#if !defined(SIMDE_X86_MMX_USE_NATIVE_TYPE) && defined(SIMDE_ENABLE_NATIVE_ALIASES) + #define SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES + typedef simde__m64 __m64; +#endif + +HEDLEY_STATIC_ASSERT(8 == sizeof(simde__m64), "__m64 size incorrect"); +HEDLEY_STATIC_ASSERT(8 == sizeof(simde__m64_private), "__m64 size incorrect"); +#if defined(SIMDE_CHECK_ALIGNMENT) && defined(SIMDE_ALIGN_OF) +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m64) == 8, "simde__m64 is not 8-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m64_private) == 8, "simde__m64_private is not 8-byte aligned"); +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde__m64_from_private(simde__m64_private v) { + simde__m64 r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64_private +simde__m64_to_private(simde__m64 v) { + simde__m64_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +#define SIMDE_X86_GENERATE_CONVERSION_FUNCTION(simde_type, source_type, isax, fragment) \ + SIMDE_FUNCTION_ATTRIBUTES \ + simde__##simde_type \ + simde__##simde_type##_from_##isax##_##fragment(source_type value) { \ + simde__##simde_type##_private r_; \ + r_.isax##_##fragment = value; \ + return simde__##simde_type##_from_private(r_); \ + } \ + \ + SIMDE_FUNCTION_ATTRIBUTES \ + source_type \ + simde__##simde_type##_to_##isax##_##fragment(simde__##simde_type value) { \ + simde__##simde_type##_private r_ = simde__##simde_type##_to_private(value); \ + return r_.isax##_##fragment; \ + } + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int8x8_t, neon, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int16x4_t, neon, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int32x2_t, neon, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int64x1_t, neon, i64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint8x8_t, neon, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint16x4_t, neon, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint32x2_t, neon, u32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint64x1_t, neon, u64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, float32x2_t, neon, f32) +#endif /* defined(SIMDE_ARM_NEON_A32V7_NATIVE) */ + +#if defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int8x8_t, mmi, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int16x4_t, mmi, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int32x2_t, mmi, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, int64_t, mmi, i64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint8x8_t, mmi, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint16x4_t, mmi, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint32x2_t, mmi, u32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m64, uint64_t, mmi, u64) +#endif /* defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) */ + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_add_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_add_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vadd_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = paddb_s(a_.mmi_i8, b_.mmi_i8); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = a_.i8 + b_.i8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] + b_.i8[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddb(a, b) simde_mm_add_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_add_pi8(a, b) simde_mm_add_pi8(a, b) +# define _m_paddb(a, b) simde_m_paddb(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_add_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_add_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vadd_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = paddh_s(a_.mmi_i16, b_.mmi_i16); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 + b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] + b_.i16[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddw(a, b) simde_mm_add_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_add_pi16(a, b) simde_mm_add_pi16(a, b) +# define _m_paddw(a, b) simde_mm_add_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_add_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_add_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vadd_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = paddw_s(a_.mmi_i32, b_.mmi_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 + b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] + b_.i32[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddd(a, b) simde_mm_add_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_add_pi32(a, b) simde_mm_add_pi32(a, b) +# define _m_paddd(a, b) simde_mm_add_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_adds_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_adds_pi8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vqadd_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = paddsb(a_.mmi_i8, b_.mmi_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + if ((((b_.i8[i]) > 0) && ((a_.i8[i]) > (INT8_MAX - (b_.i8[i]))))) { + r_.i8[i] = INT8_MAX; + } else if ((((b_.i8[i]) < 0) && ((a_.i8[i]) < (INT8_MIN - (b_.i8[i]))))) { + r_.i8[i] = INT8_MIN; + } else { + r_.i8[i] = (a_.i8[i]) + (b_.i8[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddsb(a, b) simde_mm_adds_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_adds_pi8(a, b) simde_mm_adds_pi8(a, b) +# define _m_paddsb(a, b) simde_mm_adds_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_adds_pu8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_adds_pu8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vqadd_u8(a_.neon_u8, b_.neon_u8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_u8 = paddusb(a_.mmi_u8, b_.mmi_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + const uint_fast16_t x = HEDLEY_STATIC_CAST(uint_fast16_t, a_.u8[i]) + HEDLEY_STATIC_CAST(uint_fast16_t, b_.u8[i]); + if (x > UINT8_MAX) + r_.u8[i] = UINT8_MAX; + else + r_.u8[i] = HEDLEY_STATIC_CAST(uint8_t, x); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddusb(a, b) simde_mm_adds_pu8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_adds_pu8(a, b) simde_mm_adds_pu8(a, b) +# define _m_paddusb(a, b) simde_mm_adds_pu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_adds_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_adds_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vqadd_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = paddsh(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + if ((((b_.i16[i]) > 0) && ((a_.i16[i]) > (INT16_MAX - (b_.i16[i]))))) { + r_.i16[i] = INT16_MAX; + } else if ((((b_.i16[i]) < 0) && ((a_.i16[i]) < (SHRT_MIN - (b_.i16[i]))))) { + r_.i16[i] = SHRT_MIN; + } else { + r_.i16[i] = (a_.i16[i]) + (b_.i16[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddsw(a, b) simde_mm_adds_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_adds_pi16(a, b) simde_mm_adds_pi16(a, b) +# define _m_paddsw(a, b) simde_mm_adds_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_adds_pu16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_adds_pu16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vqadd_u16(a_.neon_u16, b_.neon_u16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_u16 = paddush(a_.mmi_u16, b_.mmi_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + const uint32_t x = a_.u16[i] + b_.u16[i]; + if (x > UINT16_MAX) + r_.u16[i] = UINT16_MAX; + else + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, x); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_paddusw(a, b) simde_mm_adds_pu16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_adds_pu16(a, b) simde_mm_adds_pu16(a, b) +# define _m_paddusw(a, b) simde_mm_adds_pu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_and_si64 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_and_si64(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vand_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 & b_.i64; + #else + r_.i64[0] = a_.i64[0] & b_.i64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pand(a, b) simde_mm_and_si64(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_and_si64(a, b) simde_mm_and_si64(a, b) +# define _m_pand(a, b) simde_mm_and_si64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_andnot_si64 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_andnot_si64(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vbic_s32(b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = pandn_sw(a_.mmi_i32, b_.mmi_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f & b_.i32f; + #else + r_.u64[0] = (~(a_.u64[0])) & (b_.u64[0]); + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pandn(a, b) simde_mm_andnot_si64(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_andnot_si64(a, b) simde_mm_andnot_si64(a, b) +# define _m_pandn(a, b) simde_mm_andnot_si64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cmpeq_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cmpeq_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vceq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = pcmpeqb_s(a_.mmi_i8, b_.mmi_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] == b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pcmpeqb(a, b) simde_mm_cmpeq_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cmpeq_pi8(a, b) simde_mm_cmpeq_pi8(a, b) +# define _m_pcmpeqb(a, b) simde_mm_cmpeq_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cmpeq_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cmpeq_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vceq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = pcmpeqh_s(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] == b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pcmpeqw(a, b) simde_mm_cmpeq_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cmpeq_pi16(a, b) simde_mm_cmpeq_pi16(a, b) +# define _m_pcmpeqw(a, b) simde_mm_cmpeq_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cmpeq_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cmpeq_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vceq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = pcmpeqw_s(a_.mmi_i32, b_.mmi_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] == b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pcmpeqd(a, b) simde_mm_cmpeq_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cmpeq_pi32(a, b) simde_mm_cmpeq_pi32(a, b) +# define _m_pcmpeqd(a, b) simde_mm_cmpeq_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cmpgt_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cmpgt_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vcgt_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = pcmpgtb_s(a_.mmi_i8, b_.mmi_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] > b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pcmpgtb(a, b) simde_mm_cmpgt_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cmpgt_pi8(a, b) simde_mm_cmpgt_pi8(a, b) +# define _m_pcmpgtb(a, b) simde_mm_cmpgt_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cmpgt_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cmpgt_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vcgt_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = pcmpgth_s(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] > b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pcmpgtw(a, b) simde_mm_cmpgt_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cmpgt_pi16(a, b) simde_mm_cmpgt_pi16(a, b) +# define _m_pcmpgtw(a, b) simde_mm_cmpgt_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cmpgt_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cmpgt_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcgt_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = pcmpgtw_s(a_.mmi_i32, b_.mmi_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] > b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pcmpgtd(a, b) simde_mm_cmpgt_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cmpgt_pi32(a, b) simde_mm_cmpgt_pi32(a, b) +# define _m_pcmpgtd(a, b) simde_mm_cmpgt_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_cvtm64_si64 (simde__m64 a) { + #if defined(SIMDE_X86_MMX_NATIVE) && defined(SIMDE_ARCH_AMD64) && !defined(__PGI) + return _mm_cvtm64_si64(a); + #else + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wvector-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(10,0,0) + #pragma clang diagnostic ignored "-Wvector-conversion" + #endif + return vget_lane_s64(a_.neon_i64, 0); + HEDLEY_DIAGNOSTIC_POP + #else + return a_.i64[0]; + #endif + #endif +} +#define simde_m_to_int64(a) simde_mm_cvtm64_si64(a) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) +# define _mm_cvtm64_si64(a) simde_mm_cvtm64_si64(a) +# define _m_to_int64(a) simde_mm_cvtm64_si64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtsi32_si64 (int32_t a) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtsi32_si64(a); + #else + simde__m64_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int32_t av[sizeof(r_.neon_i32) / sizeof(r_.neon_i32[0])] = { a, 0 }; + r_.neon_i32 = vld1_s32(av); + #else + r_.i32[0] = a; + r_.i32[1] = 0; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_from_int(a) simde_mm_cvtsi32_si64(a) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cvtsi32_si64(a) simde_mm_cvtsi32_si64(a) +# define _m_from_int(a) simde_mm_cvtsi32_si64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtsi64_m64 (int64_t a) { + #if defined(SIMDE_X86_MMX_NATIVE) && defined(SIMDE_ARCH_AMD64) && !defined(__PGI) + return _mm_cvtsi64_m64(a); + #else + simde__m64_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vld1_s64(&a); + #else + r_.i64[0] = a; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_from_int64(a) simde_mm_cvtsi64_m64(a) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) +# define _mm_cvtsi64_m64(a) simde_mm_cvtsi64_m64(a) +# define _m_from_int64(a) simde_mm_cvtsi64_m64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvtsi64_si32 (simde__m64 a) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtsi64_si32(a); + #else + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wvector-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(10,0,0) + #pragma clang diagnostic ignored "-Wvector-conversion" + #endif + return vget_lane_s32(a_.neon_i32, 0); + HEDLEY_DIAGNOSTIC_POP + #else + return a_.i32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_cvtsi64_si32(a) simde_mm_cvtsi64_si32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_empty (void) { + #if defined(SIMDE_X86_MMX_NATIVE) + _mm_empty(); + #else + /* noop */ + #endif +} +#define simde_m_empty() simde_mm_empty() +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_empty() simde_mm_empty() +# define _m_empty() simde_mm_empty() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_madd_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_madd_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4_t i1 = vmull_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i32 = vpadd_s32(vget_low_s32(i1), vget_high_s32(i1)); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = pmaddhw(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i += 2) { + r_.i32[i / 2] = (a_.i16[i] * b_.i16[i]) + (a_.i16[i + 1] * b_.i16[i + 1]); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pmaddwd(a, b) simde_mm_madd_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_madd_pi16(a, b) simde_mm_madd_pi16(a, b) +# define _m_pmaddwd(a, b) simde_mm_madd_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_mulhi_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_mulhi_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int32x4_t t1 = vmull_s16(a_.neon_i16, b_.neon_i16); + const uint32x4_t t2 = vshrq_n_u32(vreinterpretq_u32_s32(t1), 16); + const uint16x4_t t3 = vmovn_u32(t2); + r_.neon_u16 = t3; + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = pmulhh(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, ((a_.i16[i] * b_.i16[i]) >> 16)); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pmulhw(a, b) simde_mm_mulhi_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_mulhi_pi16(a, b) simde_mm_mulhi_pi16(a, b) +# define _m_pmulhw(a, b) simde_mm_mulhi_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_mullo_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_mullo_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int32x4_t t1 = vmull_s16(a_.neon_i16, b_.neon_i16); + const uint16x4_t t2 = vmovn_u32(vreinterpretq_u32_s32(t1)); + r_.neon_u16 = t2; + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = pmullh(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, ((a_.i16[i] * b_.i16[i]) & 0xffff)); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pmullw(a, b) simde_mm_mullo_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_mullo_pi16(a, b) simde_mm_mullo_pi16(a, b) +# define _m_pmullw(a, b) simde_mm_mullo_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_or_si64 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_or_si64(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vorr_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 | b_.i64; + #else + r_.i64[0] = a_.i64[0] | b_.i64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_por(a, b) simde_mm_or_si64(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_or_si64(a, b) simde_mm_or_si64(a, b) +# define _m_por(a, b) simde_mm_or_si64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_packs_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_packs_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vqmovn_s16(vcombine_s16(a_.neon_i16, b_.neon_i16)); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = packsshb(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + if (a_.i16[i] < INT8_MIN) { + r_.i8[i] = INT8_MIN; + } else if (a_.i16[i] > INT8_MAX) { + r_.i8[i] = INT8_MAX; + } else { + r_.i8[i] = HEDLEY_STATIC_CAST(int8_t, a_.i16[i]); + } + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + if (b_.i16[i] < INT8_MIN) { + r_.i8[i + 4] = INT8_MIN; + } else if (b_.i16[i] > INT8_MAX) { + r_.i8[i + 4] = INT8_MAX; + } else { + r_.i8[i + 4] = HEDLEY_STATIC_CAST(int8_t, b_.i16[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_packsswb(a, b) simde_mm_packs_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_packs_pi16(a, b) simde_mm_packs_pi16(a, b) +# define _m_packsswb(a, b) simde_mm_packs_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_packs_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_packs_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vqmovn_s32(vcombine_s32(a_.neon_i32, b_.neon_i32)); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = packsswh(a_.mmi_i32, b_.mmi_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (8 / sizeof(a_.i32[0])) ; i++) { + if (a_.i32[i] < SHRT_MIN) { + r_.i16[i] = SHRT_MIN; + } else if (a_.i32[i] > INT16_MAX) { + r_.i16[i] = INT16_MAX; + } else { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, a_.i32[i]); + } + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (8 / sizeof(b_.i32[0])) ; i++) { + if (b_.i32[i] < SHRT_MIN) { + r_.i16[i + 2] = SHRT_MIN; + } else if (b_.i32[i] > INT16_MAX) { + r_.i16[i + 2] = INT16_MAX; + } else { + r_.i16[i + 2] = HEDLEY_STATIC_CAST(int16_t, b_.i32[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_packssdw(a, b) simde_mm_packs_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_packs_pi32(a, b) simde_mm_packs_pi32(a, b) +# define _m_packssdw(a, b) simde_mm_packs_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_packs_pu16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_packs_pu16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + const int16x8_t t1 = vcombine_s16(a_.neon_i16, b_.neon_i16); + + /* Set elements which are < 0 to 0 */ + const int16x8_t t2 = vandq_s16(t1, vreinterpretq_s16_u16(vcgezq_s16(t1))); + + /* Vector with all s16 elements set to UINT8_MAX */ + const int16x8_t vmax = vmovq_n_s16(HEDLEY_STATIC_CAST(int16_t, UINT8_MAX)); + + /* Elements which are within the acceptable range */ + const int16x8_t le_max = vandq_s16(t2, vreinterpretq_s16_u16(vcleq_s16(t2, vmax))); + const int16x8_t gt_max = vandq_s16(vmax, vreinterpretq_s16_u16(vcgtq_s16(t2, vmax))); + + /* Final values as 16-bit integers */ + const int16x8_t values = vorrq_s16(le_max, gt_max); + + r_.neon_u8 = vmovn_u16(vreinterpretq_u16_s16(values)); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_u8 = packushb(a_.mmi_u16, b_.mmi_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + if (a_.i16[i] > UINT8_MAX) { + r_.u8[i] = UINT8_MAX; + } else if (a_.i16[i] < 0) { + r_.u8[i] = 0; + } else { + r_.u8[i] = HEDLEY_STATIC_CAST(uint8_t, a_.i16[i]); + } + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + if (b_.i16[i] > UINT8_MAX) { + r_.u8[i + 4] = UINT8_MAX; + } else if (b_.i16[i] < 0) { + r_.u8[i + 4] = 0; + } else { + r_.u8[i + 4] = HEDLEY_STATIC_CAST(uint8_t, b_.i16[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_packuswb(a, b) simde_mm_packs_pu16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_packs_pu16(a, b) simde_mm_packs_pu16(a, b) +# define _m_packuswb(a, b) simde_mm_packs_pu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_set_pi8 (int8_t e7, int8_t e6, int8_t e5, int8_t e4, int8_t e3, int8_t e2, int8_t e1, int8_t e0) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_set_pi8(e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m64_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int8_t v[sizeof(r_.i8) / sizeof(r_.i8[0])] = { e0, e1, e2, e3, e4, e5, e6, e7 }; + r_.neon_i8 = vld1_s8(v); + #else + r_.i8[0] = e0; + r_.i8[1] = e1; + r_.i8[2] = e2; + r_.i8[3] = e3; + r_.i8[4] = e4; + r_.i8[5] = e5; + r_.i8[6] = e6; + r_.i8[7] = e7; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_set_pi8(e7, e6, e5, e4, e3, e2, e1, e0) simde_mm_set_pi8(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_set_pu8 (uint8_t e7, uint8_t e6, uint8_t e5, uint8_t e4, uint8_t e3, uint8_t e2, uint8_t e1, uint8_t e0) { + simde__m64_private r_; + + #if defined(SIMDE_X86_MMX_NATIVE) + r_.n = _mm_set_pi8( + HEDLEY_STATIC_CAST(int8_t, e7), + HEDLEY_STATIC_CAST(int8_t, e6), + HEDLEY_STATIC_CAST(int8_t, e5), + HEDLEY_STATIC_CAST(int8_t, e4), + HEDLEY_STATIC_CAST(int8_t, e3), + HEDLEY_STATIC_CAST(int8_t, e2), + HEDLEY_STATIC_CAST(int8_t, e1), + HEDLEY_STATIC_CAST(int8_t, e0)); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const uint8_t v[sizeof(r_.u8) / sizeof(r_.u8[0])] = { e0, e1, e2, e3, e4, e5, e6, e7 }; + r_.neon_u8 = vld1_u8(v); + #else + r_.u8[0] = e0; + r_.u8[1] = e1; + r_.u8[2] = e2; + r_.u8[3] = e3; + r_.u8[4] = e4; + r_.u8[5] = e5; + r_.u8[6] = e6; + r_.u8[7] = e7; + #endif + + return simde__m64_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_set_pi16 (int16_t e3, int16_t e2, int16_t e1, int16_t e0) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_set_pi16(e3, e2, e1, e0); + #else + simde__m64_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int16_t v[sizeof(r_.i16) / sizeof(r_.i16[0])] = { e0, e1, e2, e3 }; + r_.neon_i16 = vld1_s16(v); + #else + r_.i16[0] = e0; + r_.i16[1] = e1; + r_.i16[2] = e2; + r_.i16[3] = e3; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_set_pi16(e3, e2, e1, e0) simde_mm_set_pi16(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_set_pu16 (uint16_t e3, uint16_t e2, uint16_t e1, uint16_t e0) { + simde__m64_private r_; + +#if defined(SIMDE_X86_MMX_NATIVE) + r_.n = _mm_set_pi16( + HEDLEY_STATIC_CAST(int16_t, e3), + HEDLEY_STATIC_CAST(int16_t, e2), + HEDLEY_STATIC_CAST(int16_t, e1), + HEDLEY_STATIC_CAST(int16_t, e0) + ); +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const uint16_t v[sizeof(r_.u16) / sizeof(r_.u16[0])] = { e0, e1, e2, e3 }; + r_.neon_u16 = vld1_u16(v); +#else + r_.u16[0] = e0; + r_.u16[1] = e1; + r_.u16[2] = e2; + r_.u16[3] = e3; +#endif + + return simde__m64_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_set_pu32 (uint32_t e1, uint32_t e0) { + simde__m64_private r_; + +#if defined(SIMDE_X86_MMX_NATIVE) + r_.n = _mm_set_pi32( + HEDLEY_STATIC_CAST(int32_t, e1), + HEDLEY_STATIC_CAST(int32_t, e0)); +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const uint32_t v[sizeof(r_.u32) / sizeof(r_.u32[0])] = { e0, e1 }; + r_.neon_u32 = vld1_u32(v); +#else + r_.u32[0] = e0; + r_.u32[1] = e1; +#endif + + return simde__m64_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_set_pi32 (int32_t e1, int32_t e0) { + simde__m64_private r_; + +#if defined(SIMDE_X86_MMX_NATIVE) + r_.n = _mm_set_pi32(e1, e0); +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int32_t v[sizeof(r_.i32) / sizeof(r_.i32[0])] = { e0, e1 }; + r_.neon_i32 = vld1_s32(v); +#else + r_.i32[0] = e0; + r_.i32[1] = e1; +#endif + + return simde__m64_from_private(r_); +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_set_pi32(e1, e0) simde_mm_set_pi32(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_set_pi64 (int64_t e0) { + simde__m64_private r_; + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int64_t v[sizeof(r_.i64) / sizeof(r_.i64[0])] = { e0 }; + r_.neon_i64 = vld1_s64(v); +#else + r_.i64[0] = e0; +#endif + + return simde__m64_from_private(r_); +} + + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_set_f32x2 (simde_float32 e1, simde_float32 e0) { + simde__m64_private r_; + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const simde_float32 v[sizeof(r_.f32) / sizeof(r_.f32[0])] = { e0, e1 }; + r_.neon_f32 = vld1_f32(v); +#else + r_.f32[0] = e0; + r_.f32[1] = e1; +#endif + + return simde__m64_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_set1_pi8 (int8_t a) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_set1_pi8(a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + simde__m64_private r_; + r_.neon_i8 = vmov_n_s8(a); + return simde__m64_from_private(r_); + #else + return simde_mm_set_pi8(a, a, a, a, a, a, a, a); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_set1_pi8(a) simde_mm_set1_pi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_set1_pi16 (int16_t a) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_set1_pi16(a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + simde__m64_private r_; + r_.neon_i16 = vmov_n_s16(a); + return simde__m64_from_private(r_); + #else + return simde_mm_set_pi16(a, a, a, a); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_set1_pi16(a) simde_mm_set1_pi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_set1_pi32 (int32_t a) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_set1_pi32(a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + simde__m64_private r_; + r_.neon_i32 = vmov_n_s32(a); + return simde__m64_from_private(r_); + #else + return simde_mm_set_pi32(a, a); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_set1_pi32(a) simde_mm_set1_pi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_setr_pi8 (int8_t e7, int8_t e6, int8_t e5, int8_t e4, int8_t e3, int8_t e2, int8_t e1, int8_t e0) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_setr_pi8(e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm_set_pi8(e0, e1, e2, e3, e4, e5, e6, e7); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_setr_pi8(e7, e6, e5, e4, e3, e2, e1, e0) simde_mm_setr_pi8(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_setr_pi16 (int16_t e3, int16_t e2, int16_t e1, int16_t e0) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_setr_pi16(e3, e2, e1, e0); + #else + return simde_mm_set_pi16(e0, e1, e2, e3); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_setr_pi16(e3, e2, e1, e0) simde_mm_setr_pi16(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_setr_pi32 (int32_t e1, int32_t e0) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_setr_pi32(e1, e0); + #else + return simde_mm_set_pi32(e0, e1); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_setr_pi32(e1, e0) simde_mm_setr_pi32(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_setzero_si64 (void) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_setzero_si64(); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + simde__m64_private r_; + r_.neon_u32 = vmov_n_u32(0); + return simde__m64_from_private(r_); + #else + return simde_mm_set_pi32(0, 0); + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_setzero_si64() simde_mm_setzero_si64() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_load_si64 (const void* mem_addr) { + simde__m64 r; + simde_memcpy(&r, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m64), sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_loadu_si64 (const void* mem_addr) { + simde__m64 r; + simde_memcpy(&r, mem_addr, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_x_mm_store_si64 (void* mem_addr, simde__m64 value) { + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m64), &value, sizeof(value)); +} + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_x_mm_storeu_si64 (void* mem_addr, simde__m64 value) { + simde_memcpy(mem_addr, &value, sizeof(value)); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_x_mm_setone_si64 (void) { + return simde_mm_set1_pi32(~INT32_C(0)); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sll_pi16 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sll_pi16(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wvector-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(10,0,0) + #pragma clang diagnostic ignored "-Wvector-conversion" + #endif + r_.neon_i16 = vshl_s16(a_.neon_i16, vmov_n_s16(HEDLEY_STATIC_CAST(int16_t, vget_lane_u64(count_.neon_u64, 0)))); + HEDLEY_DIAGNOSTIC_POP + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_BUG_CLANG_POWER9_16x4_BAD_SHIFT) + if (HEDLEY_UNLIKELY(count_.u64[0] > 15)) + return simde_mm_setzero_si64(); + + r_.i16 = a_.i16 << HEDLEY_STATIC_CAST(int16_t, count_.u64[0]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 << count_.u64[0]; + #else + if (HEDLEY_UNLIKELY(count_.u64[0] > 15)) { + simde_memset(&r_, 0, sizeof(r_)); + return simde__m64_from_private(r_); + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, a_.u16[i] << count_.u64[0]); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psllw(a, count) simde_mm_sll_pi16(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sll_pi16(a, count) simde_mm_sll_pi16(a, count) +# define _m_psllw(a, count) simde_mm_sll_pi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sll_pi32 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sll_pi32(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wvector-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(10,0,0) + #pragma clang diagnostic ignored "-Wvector-conversion" + #endif + r_.neon_i32 = vshl_s32(a_.neon_i32, vmov_n_s32(HEDLEY_STATIC_CAST(int32_t, vget_lane_u64(count_.neon_u64, 0)))); + HEDLEY_DIAGNOSTIC_POP + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 << count_.u64[0]; + #else + if (HEDLEY_UNLIKELY(count_.u64[0] > 31)) { + simde_memset(&r_, 0, sizeof(r_)); + return simde__m64_from_private(r_); + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] << count_.u64[0]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pslld(a, count) simde_mm_sll_pi32(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sll_pi32(a, count) simde_mm_sll_pi32(a, count) +# define _m_pslld(a, count) simde_mm_sll_pi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_slli_pi16 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_slli_pi16(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_BUG_CLANG_POWER9_16x4_BAD_SHIFT) + if (HEDLEY_UNLIKELY(count > 15)) + return simde_mm_setzero_si64(); + + r_.i16 = a_.i16 << HEDLEY_STATIC_CAST(int16_t, count); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 << count; + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vshl_s16(a_.neon_i16, vmov_n_s16((int16_t) count)); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = psllh_s(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, a_.u16[i] << count); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psllwi(a, count) simde_mm_slli_pi16(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_slli_pi16(a, count) simde_mm_slli_pi16(a, count) +# define _m_psllwi(a, count) simde_mm_slli_pi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_slli_pi32 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_slli_pi32(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 << count; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vshl_s32(a_.neon_i32, vmov_n_s32((int32_t) count)); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = psllw_s(a_.mmi_i32, b_.mmi_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] << count; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pslldi(a, b) simde_mm_slli_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_slli_pi32(a, count) simde_mm_slli_pi32(a, count) +# define _m_pslldi(a, count) simde_mm_slli_pi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_slli_si64 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_slli_si64(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i64 = a_.i64 << count; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vshl_s64(a_.neon_i64, vmov_n_s64((int64_t) count)); + #else + r_.u64[0] = a_.u64[0] << count; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psllqi(a, count) simde_mm_slli_si64(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_slli_si64(a, count) simde_mm_slli_si64(a, count) +# define _m_psllqi(a, count) simde_mm_slli_si64(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sll_si64 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sll_si64(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vshl_s64(a_.neon_i64, count_.neon_i64); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 << count_.i64; + #else + if (HEDLEY_UNLIKELY(count_.u64[0] > 63)) { + simde_memset(&r_, 0, sizeof(r_)); + return simde__m64_from_private(r_); + } + + r_.u64[0] = a_.u64[0] << count_.u64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psllq(a, count) simde_mm_sll_si64(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sll_si64(a, count) simde_mm_sll_si64(a, count) +# define _m_psllq(a, count) simde_mm_sll_si64(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srl_pi16 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_srl_pi16(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_BUG_CLANG_POWER9_16x4_BAD_SHIFT) + if (HEDLEY_UNLIKELY(count_.u64[0] > 15)) + return simde_mm_setzero_si64(); + + r_.i16 = a_.i16 >> HEDLEY_STATIC_CAST(int16_t, count_.u64[0]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u16 = a_.u16 >> count_.u64[0]; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vshl_u16(a_.neon_u16, vmov_n_s16(-((int16_t) vget_lane_u64(count_.neon_u64, 0)))); + #else + if (HEDLEY_UNLIKELY(count_.u64[0] > 15)) { + simde_memset(&r_, 0, sizeof(r_)); + return simde__m64_from_private(r_); + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < sizeof(r_.u16) / sizeof(r_.u16[0]) ; i++) { + r_.u16[i] = a_.u16[i] >> count_.u64[0]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrlw(a, count) simde_mm_srl_pi16(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srl_pi16(a, count) simde_mm_srl_pi16(a, count) +# define _m_psrlw(a, count) simde_mm_srl_pi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srl_pi32 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_srl_pi32(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = a_.u32 >> count_.u64[0]; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vshl_u32(a_.neon_u32, vmov_n_s32(-((int32_t) vget_lane_u64(count_.neon_u64, 0)))); + #else + if (HEDLEY_UNLIKELY(count_.u64[0] > 31)) { + simde_memset(&r_, 0, sizeof(r_)); + return simde__m64_from_private(r_); + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < sizeof(r_.u32) / sizeof(r_.u32[0]) ; i++) { + r_.u32[i] = a_.u32[i] >> count_.u64[0]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrld(a, count) simde_mm_srl_pi32(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srl_pi32(a, count) simde_mm_srl_pi32(a, count) +# define _m_psrld(a, count) simde_mm_srl_pi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srli_pi16 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_srli_pi16(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u16 = a_.u16 >> count; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vshl_u16(a_.neon_u16, vmov_n_s16(-((int16_t) count))); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = psrlh_s(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = a_.u16[i] >> count; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrlwi(a, count) simde_mm_srli_pi16(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srli_pi16(a, count) simde_mm_srli_pi16(a, count) +# define _m_psrlwi(a, count) simde_mm_srli_pi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srli_pi32 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_srli_pi32(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = a_.u32 >> count; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vshl_u32(a_.neon_u32, vmov_n_s32(-((int32_t) count))); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = psrlw_s(a_.mmi_i32, b_.mmi_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] >> count; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrldi(a, count) simde_mm_srli_pi32(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srli_pi32(a, count) simde_mm_srli_pi32(a, count) +# define _m_psrldi(a, count) simde_mm_srli_pi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srli_si64 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_srli_si64(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u64 = vshl_u64(a_.neon_u64, vmov_n_s64(-count)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = a_.u64 >> count; + #else + r_.u64[0] = a_.u64[0] >> count; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrlqi(a, count) simde_mm_srli_si64(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srli_si64(a, count) simde_mm_srli_si64(a, count) +# define _m_psrlqi(a, count) simde_mm_srli_si64(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srl_si64 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_srl_si64(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vshl_u64(a_.neon_u64, vneg_s64(count_.neon_i64)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.u64 = a_.u64 >> count_.u64; + #else + if (HEDLEY_UNLIKELY(count_.u64[0] > 63)) { + simde_memset(&r_, 0, sizeof(r_)); + return simde__m64_from_private(r_); + } + + r_.u64[0] = a_.u64[0] >> count_.u64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrlq(a, count) simde_mm_srl_si64(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srl_si64(a, count) simde_mm_srl_si64(a, count) +# define _m_psrlq(a, count) simde_mm_srl_si64(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srai_pi16 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_srai_pi16(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 >> (count & 0xff); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vshl_s16(a_.neon_i16, vmov_n_s16(-HEDLEY_STATIC_CAST(int16_t, count))); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = psrah_s(a_.mmi_i16, count); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] >> (count & 0xff); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrawi(a, count) simde_mm_srai_pi16(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srai_pi16(a, count) simde_mm_srai_pi16(a, count) +# define _m_psrawi(a, count) simde_mm_srai_pi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_srai_pi32 (simde__m64 a, int count) { + #if defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_srai_pi32(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 >> (count & 0xff); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vshl_s32(a_.neon_i32, vmov_n_s32(-HEDLEY_STATIC_CAST(int32_t, count))); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = psraw_s(a_.mmi_i32, count); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] >> (count & 0xff); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psradi(a, count) simde_mm_srai_pi32(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_srai_pi32(a, count) simde_mm_srai_pi32(a, count) +# define _m_psradi(a, count) simde_mm_srai_pi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sra_pi16 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sra_pi16(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + const int cnt = HEDLEY_STATIC_CAST(int, (count_.i64[0] > 15 ? 15 : count_.i64[0])); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 >> cnt; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vshl_s16(a_.neon_i16, vmov_n_s16(-HEDLEY_STATIC_CAST(int16_t, vget_lane_u64(count_.neon_u64, 0)))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] >> cnt; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psraw(a, count) simde_mm_sra_pi16(a, count) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sra_pi16(a, count) simde_mm_sra_pi16(a, count) +# define _m_psraw(a, count) simde_mm_sra_pi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sra_pi32 (simde__m64 a, simde__m64 count) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sra_pi32(a, count); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private count_ = simde__m64_to_private(count); + const int32_t cnt = (count_.u64[0] > 31) ? 31 : HEDLEY_STATIC_CAST(int32_t, count_.u64[0]); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 >> cnt; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vshl_s32(a_.neon_i32, vmov_n_s32(-HEDLEY_STATIC_CAST(int32_t, vget_lane_u64(count_.neon_u64, 0)))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] >> cnt; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psrad(a, b) simde_mm_sra_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sra_pi32(a, count) simde_mm_sra_pi32(a, count) +# define _m_psrad(a, count) simde_mm_sra_pi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sub_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sub_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vsub_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = psubb_s(a_.mmi_i8, b_.mmi_i8); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = a_.i8 - b_.i8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] - b_.i8[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubb(a, b) simde_mm_sub_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sub_pi8(a, b) simde_mm_sub_pi8(a, b) +# define _m_psubb(a, b) simde_mm_sub_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sub_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sub_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vsub_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = psubh_s(a_.mmi_i16, b_.mmi_i16); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 - b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] - b_.i16[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubw(a, b) simde_mm_sub_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sub_pi16(a, b) simde_mm_sub_pi16(a, b) +# define _m_psubw(a, b) simde_mm_sub_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sub_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_sub_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vsub_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = psubw_s(a_.mmi_i32, b_.mmi_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 - b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] - b_.i32[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubd(a, b) simde_mm_sub_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_sub_pi32(a, b) simde_mm_sub_pi32(a, b) +# define _m_psubd(a, b) simde_mm_sub_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_subs_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_subs_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vqsub_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = psubsb(a_.mmi_i8, b_.mmi_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + if (((b_.i8[i]) > 0 && (a_.i8[i]) < INT8_MIN + (b_.i8[i]))) { + r_.i8[i] = INT8_MIN; + } else if ((b_.i8[i]) < 0 && (a_.i8[i]) > INT8_MAX + (b_.i8[i])) { + r_.i8[i] = INT8_MAX; + } else { + r_.i8[i] = (a_.i8[i]) - (b_.i8[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubsb(a, b) simde_mm_subs_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_subs_pi8(a, b) simde_mm_subs_pi8(a, b) +# define _m_psubsb(a, b) simde_mm_subs_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_subs_pu8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_subs_pu8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vqsub_u8(a_.neon_u8, b_.neon_u8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_u8 = psubusb(a_.mmi_u8, b_.mmi_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + const int32_t x = a_.u8[i] - b_.u8[i]; + if (x < 0) { + r_.u8[i] = 0; + } else if (x > UINT8_MAX) { + r_.u8[i] = UINT8_MAX; + } else { + r_.u8[i] = HEDLEY_STATIC_CAST(uint8_t, x); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubusb(a, b) simde_mm_subs_pu8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_subs_pu8(a, b) simde_mm_subs_pu8(a, b) +# define _m_psubusb(a, b) simde_mm_subs_pu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_subs_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_subs_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vqsub_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = psubsh(a_.mmi_i16, b_.mmi_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + if (((b_.i16[i]) > 0 && (a_.i16[i]) < SHRT_MIN + (b_.i16[i]))) { + r_.i16[i] = SHRT_MIN; + } else if ((b_.i16[i]) < 0 && (a_.i16[i]) > INT16_MAX + (b_.i16[i])) { + r_.i16[i] = INT16_MAX; + } else { + r_.i16[i] = (a_.i16[i]) - (b_.i16[i]); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubsw(a, b) simde_mm_subs_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_subs_pi16(a, b) simde_mm_subs_pi16(a, b) +# define _m_psubsw(a, b) simde_mm_subs_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_subs_pu16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_subs_pu16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vqsub_u16(a_.neon_u16, b_.neon_u16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_u16 = psubush(a_.mmi_u16, b_.mmi_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + const int x = a_.u16[i] - b_.u16[i]; + if (x < 0) { + r_.u16[i] = 0; + } else if (x > UINT16_MAX) { + r_.u16[i] = UINT16_MAX; + } else { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, x); + } + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psubusw(a, b) simde_mm_subs_pu16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_subs_pu16(a, b) simde_mm_subs_pu16(a, b) +# define _m_psubusw(a, b) simde_mm_subs_pu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_unpackhi_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_unpackhi_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i8 = vzip2_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i8 = SIMDE_SHUFFLE_VECTOR_(8, 8, a_.i8, b_.i8, 4, 12, 5, 13, 6, 14, 7, 15); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = punpckhbh_s(a_.mmi_i8, b_.mmi_i8); + #else + r_.i8[0] = a_.i8[4]; + r_.i8[1] = b_.i8[4]; + r_.i8[2] = a_.i8[5]; + r_.i8[3] = b_.i8[5]; + r_.i8[4] = a_.i8[6]; + r_.i8[5] = b_.i8[6]; + r_.i8[6] = a_.i8[7]; + r_.i8[7] = b_.i8[7]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_punpckhbw(a, b) simde_mm_unpackhi_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_unpackhi_pi8(a, b) simde_mm_unpackhi_pi8(a, b) +# define _m_punpckhbw(a, b) simde_mm_unpackhi_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_unpackhi_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_unpackhi_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vzip2_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = punpckhhw_s(a_.mmi_i16, b_.mmi_i16); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 8, a_.i16, b_.i16, 2, 6, 3, 7); + #else + r_.i16[0] = a_.i16[2]; + r_.i16[1] = b_.i16[2]; + r_.i16[2] = a_.i16[3]; + r_.i16[3] = b_.i16[3]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_punpckhwd(a, b) simde_mm_unpackhi_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_unpackhi_pi16(a, b) simde_mm_unpackhi_pi16(a, b) +# define _m_punpckhwd(a, b) simde_mm_unpackhi_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_unpackhi_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_unpackhi_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vzip2_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = punpckhwd_s(a_.mmi_i32, b_.mmi_i32); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 8, a_.i32, b_.i32, 1, 3); + #else + r_.i32[0] = a_.i32[1]; + r_.i32[1] = b_.i32[1]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_punpckhdq(a, b) simde_mm_unpackhi_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_unpackhi_pi32(a, b) simde_mm_unpackhi_pi32(a, b) +# define _m_punpckhdq(a, b) simde_mm_unpackhi_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_unpacklo_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_unpacklo_pi8(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i8 = vzip1_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i8 = punpcklbh_s(a_.mmi_i8, b_.mmi_i8); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i8 = SIMDE_SHUFFLE_VECTOR_(8, 8, a_.i8, b_.i8, 0, 8, 1, 9, 2, 10, 3, 11); + #else + r_.i8[0] = a_.i8[0]; + r_.i8[1] = b_.i8[0]; + r_.i8[2] = a_.i8[1]; + r_.i8[3] = b_.i8[1]; + r_.i8[4] = a_.i8[2]; + r_.i8[5] = b_.i8[2]; + r_.i8[6] = a_.i8[3]; + r_.i8[7] = b_.i8[3]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_punpcklbw(a, b) simde_mm_unpacklo_pi8(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_unpacklo_pi8(a, b) simde_mm_unpacklo_pi8(a, b) +# define _m_punpcklbw(a, b) simde_mm_unpacklo_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_unpacklo_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_unpacklo_pi16(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vzip1_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i16 = punpcklhw_s(a_.mmi_i16, b_.mmi_i16); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 8, a_.i16, b_.i16, 0, 4, 1, 5); + #else + r_.i16[0] = a_.i16[0]; + r_.i16[1] = b_.i16[0]; + r_.i16[2] = a_.i16[1]; + r_.i16[3] = b_.i16[1]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_punpcklwd(a, b) simde_mm_unpacklo_pi16(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_unpacklo_pi16(a, b) simde_mm_unpacklo_pi16(a, b) +# define _m_punpcklwd(a, b) simde_mm_unpacklo_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_unpacklo_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_unpacklo_pi32(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vzip1_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_MIPS_LOONGSON_MMI_NATIVE) + r_.mmi_i32 = punpcklwd_s(a_.mmi_i32, b_.mmi_i32); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 8, a_.i32, b_.i32, 0, 2); + #else + r_.i32[0] = a_.i32[0]; + r_.i32[1] = b_.i32[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_punpckldq(a, b) simde_mm_unpacklo_pi32(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_unpacklo_pi32(a, b) simde_mm_unpacklo_pi32(a, b) +# define _m_punpckldq(a, b) simde_mm_unpacklo_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_xor_si64 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _mm_xor_si64(a, b); + #else + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = veor_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #else + r_.u64[0] = a_.u64[0] ^ b_.u64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pxor(a, b) simde_mm_xor_si64(a, b) +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _mm_xor_si64(a, b) simde_mm_xor_si64(a, b) +# define _m_pxor(a, b) simde_mm_xor_si64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_m_to_int (simde__m64 a) { + #if defined(SIMDE_X86_MMX_NATIVE) + return _m_to_int(a); + #else + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wvector-conversion") && SIMDE_DETECT_CLANG_VERSION_NOT(10,0,0) + #pragma clang diagnostic ignored "-Wvector-conversion" + #endif + return vget_lane_s32(a_.neon_i32, 0); + HEDLEY_DIAGNOSTIC_POP + #else + return a_.i32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_MMX_ENABLE_NATIVE_ALIASES) +# define _m_to_int(a) simde_m_to_int(a) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_MMX_H) */ +/* :: End ../simde/simde/x86/mmx.h :: */ + +#if defined(_WIN32) + #include +#endif + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_16 int8_t i8 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int16_t i16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int32_t i32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int64_t i64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint8_t u8 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint16_t u16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint32_t u32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint64_t u64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_16 simde_int128 i128 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 simde_uint128 u128 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #endif + SIMDE_ALIGN_TO_16 simde_float32 f32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int_fast32_t i32f SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint_fast32_t u32f SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_16 int8_t i8[16]; + SIMDE_ALIGN_TO_16 int16_t i16[8]; + SIMDE_ALIGN_TO_16 int32_t i32[4]; + SIMDE_ALIGN_TO_16 int64_t i64[2]; + SIMDE_ALIGN_TO_16 uint8_t u8[16]; + SIMDE_ALIGN_TO_16 uint16_t u16[8]; + SIMDE_ALIGN_TO_16 uint32_t u32[4]; + SIMDE_ALIGN_TO_16 uint64_t u64[2]; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_16 simde_int128 i128[1]; + SIMDE_ALIGN_TO_16 simde_uint128 u128[1]; + #endif + SIMDE_ALIGN_TO_16 simde_float32 f32[4]; + SIMDE_ALIGN_TO_16 int_fast32_t i32f[16 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_16 uint_fast32_t u32f[16 / sizeof(uint_fast32_t)]; + #endif + + SIMDE_ALIGN_TO_16 simde__m64_private m64_private[2]; + SIMDE_ALIGN_TO_16 simde__m64 m64[2]; + + #if defined(SIMDE_X86_SSE_NATIVE) + SIMDE_ALIGN_TO_16 __m128 n; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_TO_16 int8x16_t neon_i8; + SIMDE_ALIGN_TO_16 int16x8_t neon_i16; + SIMDE_ALIGN_TO_16 int32x4_t neon_i32; + SIMDE_ALIGN_TO_16 int64x2_t neon_i64; + SIMDE_ALIGN_TO_16 uint8x16_t neon_u8; + SIMDE_ALIGN_TO_16 uint16x8_t neon_u16; + SIMDE_ALIGN_TO_16 uint32x4_t neon_u32; + SIMDE_ALIGN_TO_16 uint64x2_t neon_u64; + SIMDE_ALIGN_TO_16 float32x4_t neon_f32; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + SIMDE_ALIGN_TO_16 float64x2_t neon_f64; + #endif + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + SIMDE_ALIGN_TO_16 v128_t wasm_v128; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) altivec_u8; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) altivec_u16; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed char) altivec_i8; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed short) altivec_i16; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(float) altivec_f32; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) altivec_u64; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed long long) altivec_i64; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(double) altivec_f64; + #endif + #endif +} simde__m128_private; + +#if defined(SIMDE_X86_SSE_NATIVE) + typedef __m128 simde__m128; +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + typedef float32x4_t simde__m128; +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + typedef v128_t simde__m128; +#elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + typedef SIMDE_POWER_ALTIVEC_VECTOR(float) simde__m128; +#elif defined(SIMDE_VECTOR_SUBSCRIPT) + typedef simde_float32 simde__m128 SIMDE_ALIGN_TO_16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; +#else + typedef simde__m128_private simde__m128; +#endif + +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + typedef simde__m128 __m128; +#endif + +HEDLEY_STATIC_ASSERT(16 == sizeof(simde__m128), "simde__m128 size incorrect"); +HEDLEY_STATIC_ASSERT(16 == sizeof(simde__m128_private), "simde__m128_private size incorrect"); +#if defined(SIMDE_CHECK_ALIGNMENT) && defined(SIMDE_ALIGN_OF) +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m128) == 16, "simde__m128 is not 16-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m128_private) == 16, "simde__m128_private is not 16-byte aligned"); +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde__m128_from_private(simde__m128_private v) { + simde__m128 r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128_private +simde__m128_to_private(simde__m128 v) { + simde__m128_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, int8x16_t, neon, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, int16x8_t, neon, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, int32x4_t, neon, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, int64x2_t, neon, i64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, uint8x16_t, neon, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, uint16x8_t, neon, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, uint32x4_t, neon, u32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, uint64x2_t, neon, u64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, float32x4_t, neon, f32) + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, float64x2_t, neon, f64) + #endif +#endif /* defined(SIMDE_ARM_NEON_A32V7_NATIVE) */ + +#if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(signed char), altivec, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(signed short), altivec, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(signed int), altivec, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(unsigned char), altivec, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(unsigned short), altivec, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(unsigned int), altivec, u32) + + #if defined(SIMDE_BUG_GCC_95782) + SIMDE_FUNCTION_ATTRIBUTES + SIMDE_POWER_ALTIVEC_VECTOR(float) + simde__m128_to_altivec_f32(simde__m128 value) { + simde__m128_private r_ = simde__m128_to_private(value); + return r_.altivec_f32; + } + + SIMDE_FUNCTION_ATTRIBUTES + simde__m128 + simde__m128_from_altivec_f32(SIMDE_POWER_ALTIVEC_VECTOR(float) value) { + simde__m128_private r_; + r_.altivec_f32 = value; + return simde__m128_from_private(r_); + } + #else + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(float), altivec, f32) + #endif + + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(signed long long), altivec, i64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), altivec, u64) + #endif +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128, v128_t, wasm, v128); +#endif /* defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) */ + +enum { + #if defined(SIMDE_X86_SSE_NATIVE) + SIMDE_MM_ROUND_NEAREST = _MM_ROUND_NEAREST, + SIMDE_MM_ROUND_DOWN = _MM_ROUND_DOWN, + SIMDE_MM_ROUND_UP = _MM_ROUND_UP, + SIMDE_MM_ROUND_TOWARD_ZERO = _MM_ROUND_TOWARD_ZERO + #else + SIMDE_MM_ROUND_NEAREST = 0x0000, + SIMDE_MM_ROUND_DOWN = 0x2000, + SIMDE_MM_ROUND_UP = 0x4000, + SIMDE_MM_ROUND_TOWARD_ZERO = 0x6000 + #endif +}; + +#if defined(_MM_FROUND_TO_NEAREST_INT) +# define SIMDE_MM_FROUND_TO_NEAREST_INT _MM_FROUND_TO_NEAREST_INT +# define SIMDE_MM_FROUND_TO_NEG_INF _MM_FROUND_TO_NEG_INF +# define SIMDE_MM_FROUND_TO_POS_INF _MM_FROUND_TO_POS_INF +# define SIMDE_MM_FROUND_TO_ZERO _MM_FROUND_TO_ZERO +# define SIMDE_MM_FROUND_CUR_DIRECTION _MM_FROUND_CUR_DIRECTION + +# define SIMDE_MM_FROUND_RAISE_EXC _MM_FROUND_RAISE_EXC +# define SIMDE_MM_FROUND_NO_EXC _MM_FROUND_NO_EXC +#else +# define SIMDE_MM_FROUND_TO_NEAREST_INT 0x00 +# define SIMDE_MM_FROUND_TO_NEG_INF 0x01 +# define SIMDE_MM_FROUND_TO_POS_INF 0x02 +# define SIMDE_MM_FROUND_TO_ZERO 0x03 +# define SIMDE_MM_FROUND_CUR_DIRECTION 0x04 + +# define SIMDE_MM_FROUND_RAISE_EXC 0x00 +# define SIMDE_MM_FROUND_NO_EXC 0x08 +#endif + +#define SIMDE_MM_FROUND_NINT \ + (SIMDE_MM_FROUND_TO_NEAREST_INT | SIMDE_MM_FROUND_RAISE_EXC) +#define SIMDE_MM_FROUND_FLOOR \ + (SIMDE_MM_FROUND_TO_NEG_INF | SIMDE_MM_FROUND_RAISE_EXC) +#define SIMDE_MM_FROUND_CEIL \ + (SIMDE_MM_FROUND_TO_POS_INF | SIMDE_MM_FROUND_RAISE_EXC) +#define SIMDE_MM_FROUND_TRUNC \ + (SIMDE_MM_FROUND_TO_ZERO | SIMDE_MM_FROUND_RAISE_EXC) +#define SIMDE_MM_FROUND_RINT \ + (SIMDE_MM_FROUND_CUR_DIRECTION | SIMDE_MM_FROUND_RAISE_EXC) +#define SIMDE_MM_FROUND_NEARBYINT \ + (SIMDE_MM_FROUND_CUR_DIRECTION | SIMDE_MM_FROUND_NO_EXC) + +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) && !defined(_MM_FROUND_TO_NEAREST_INT) +# define _MM_FROUND_TO_NEAREST_INT SIMDE_MM_FROUND_TO_NEAREST_INT +# define _MM_FROUND_TO_NEG_INF SIMDE_MM_FROUND_TO_NEG_INF +# define _MM_FROUND_TO_POS_INF SIMDE_MM_FROUND_TO_POS_INF +# define _MM_FROUND_TO_ZERO SIMDE_MM_FROUND_TO_ZERO +# define _MM_FROUND_CUR_DIRECTION SIMDE_MM_FROUND_CUR_DIRECTION +# define _MM_FROUND_RAISE_EXC SIMDE_MM_FROUND_RAISE_EXC +# define _MM_FROUND_NINT SIMDE_MM_FROUND_NINT +# define _MM_FROUND_FLOOR SIMDE_MM_FROUND_FLOOR +# define _MM_FROUND_CEIL SIMDE_MM_FROUND_CEIL +# define _MM_FROUND_TRUNC SIMDE_MM_FROUND_TRUNC +# define _MM_FROUND_RINT SIMDE_MM_FROUND_RINT +# define _MM_FROUND_NEARBYINT SIMDE_MM_FROUND_NEARBYINT +#endif + +#if defined(_MM_EXCEPT_INVALID) +# define SIMDE_MM_EXCEPT_INVALID _MM_EXCEPT_INVALID +#else +# define SIMDE_MM_EXCEPT_INVALID (0x0001) +#endif +#if defined(_MM_EXCEPT_DENORM) +# define SIMDE_MM_EXCEPT_DENORM _MM_EXCEPT_DENORM +#else +# define SIMDE_MM_EXCEPT_DENORM (0x0002) +#endif +#if defined(_MM_EXCEPT_DIV_ZERO) +# define SIMDE_MM_EXCEPT_DIV_ZERO _MM_EXCEPT_DIV_ZERO +#else +# define SIMDE_MM_EXCEPT_DIV_ZERO (0x0004) +#endif +#if defined(_MM_EXCEPT_OVERFLOW) +# define SIMDE_MM_EXCEPT_OVERFLOW _MM_EXCEPT_OVERFLOW +#else +# define SIMDE_MM_EXCEPT_OVERFLOW (0x0008) +#endif +#if defined(_MM_EXCEPT_UNDERFLOW) +# define SIMDE_MM_EXCEPT_UNDERFLOW _MM_EXCEPT_UNDERFLOW +#else +# define SIMDE_MM_EXCEPT_UNDERFLOW (0x0010) +#endif +#if defined(_MM_EXCEPT_INEXACT) +# define SIMDE_MM_EXCEPT_INEXACT _MM_EXCEPT_INEXACT +#else +# define SIMDE_MM_EXCEPT_INEXACT (0x0020) +#endif +#if defined(_MM_EXCEPT_MASK) +# define SIMDE_MM_EXCEPT_MASK _MM_EXCEPT_MASK +#else +# define SIMDE_MM_EXCEPT_MASK \ + (SIMDE_MM_EXCEPT_INVALID | SIMDE_MM_EXCEPT_DENORM | \ + SIMDE_MM_EXCEPT_DIV_ZERO | SIMDE_MM_EXCEPT_OVERFLOW | \ + SIMDE_MM_EXCEPT_UNDERFLOW | SIMDE_MM_EXCEPT_INEXACT) +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_EXCEPT_INVALID SIMDE_MM_EXCEPT_INVALID + #define _MM_EXCEPT_DENORM SIMDE_MM_EXCEPT_DENORM + #define _MM_EXCEPT_DIV_ZERO SIMDE_MM_EXCEPT_DIV_ZERO + #define _MM_EXCEPT_OVERFLOW SIMDE_MM_EXCEPT_OVERFLOW + #define _MM_EXCEPT_UNDERFLOW SIMDE_MM_EXCEPT_UNDERFLOW + #define _MM_EXCEPT_INEXACT SIMDE_MM_EXCEPT_INEXACT + #define _MM_EXCEPT_MASK SIMDE_MM_EXCEPT_MASK +#endif + +#if defined(_MM_MASK_INVALID) +# define SIMDE_MM_MASK_INVALID _MM_MASK_INVALID +#else +# define SIMDE_MM_MASK_INVALID (0x0080) +#endif +#if defined(_MM_MASK_DENORM) +# define SIMDE_MM_MASK_DENORM _MM_MASK_DENORM +#else +# define SIMDE_MM_MASK_DENORM (0x0100) +#endif +#if defined(_MM_MASK_DIV_ZERO) +# define SIMDE_MM_MASK_DIV_ZERO _MM_MASK_DIV_ZERO +#else +# define SIMDE_MM_MASK_DIV_ZERO (0x0200) +#endif +#if defined(_MM_MASK_OVERFLOW) +# define SIMDE_MM_MASK_OVERFLOW _MM_MASK_OVERFLOW +#else +# define SIMDE_MM_MASK_OVERFLOW (0x0400) +#endif +#if defined(_MM_MASK_UNDERFLOW) +# define SIMDE_MM_MASK_UNDERFLOW _MM_MASK_UNDERFLOW +#else +# define SIMDE_MM_MASK_UNDERFLOW (0x0800) +#endif +#if defined(_MM_MASK_INEXACT) +# define SIMDE_MM_MASK_INEXACT _MM_MASK_INEXACT +#else +# define SIMDE_MM_MASK_INEXACT (0x1000) +#endif +#if defined(_MM_MASK_MASK) +# define SIMDE_MM_MASK_MASK _MM_MASK_MASK +#else +# define SIMDE_MM_MASK_MASK \ + (SIMDE_MM_MASK_INVALID | SIMDE_MM_MASK_DENORM | \ + SIMDE_MM_MASK_DIV_ZERO | SIMDE_MM_MASK_OVERFLOW | \ + SIMDE_MM_MASK_UNDERFLOW | SIMDE_MM_MASK_INEXACT) +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_MASK_INVALID SIMDE_MM_MASK_INVALID + #define _MM_MASK_DENORM SIMDE_MM_MASK_DENORM + #define _MM_MASK_DIV_ZERO SIMDE_MM_MASK_DIV_ZERO + #define _MM_MASK_OVERFLOW SIMDE_MM_MASK_OVERFLOW + #define _MM_MASK_UNDERFLOW SIMDE_MM_MASK_UNDERFLOW + #define _MM_MASK_INEXACT SIMDE_MM_MASK_INEXACT + #define _MM_MASK_MASK SIMDE_MM_MASK_MASK +#endif + +#if defined(_MM_FLUSH_ZERO_MASK) +# define SIMDE_MM_FLUSH_ZERO_MASK _MM_FLUSH_ZERO_MASK +#else +# define SIMDE_MM_FLUSH_ZERO_MASK (0x8000) +#endif +#if defined(_MM_FLUSH_ZERO_ON) +# define SIMDE_MM_FLUSH_ZERO_ON _MM_FLUSH_ZERO_ON +#else +# define SIMDE_MM_FLUSH_ZERO_ON (0x8000) +#endif +#if defined(_MM_FLUSH_ZERO_OFF) +# define SIMDE_MM_FLUSH_ZERO_OFF _MM_FLUSH_ZERO_OFF +#else +# define SIMDE_MM_FLUSH_ZERO_OFF (0x0000) +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_FLUSH_ZERO_MASK SIMDE_MM_FLUSH_ZERO_MASK + #define _MM_FLUSH_ZERO_ON SIMDE_MM_FLUSH_ZERO_ON + #define _MM_FLUSH_ZERO_OFF SIMDE_MM_FLUSH_ZERO_OFF +#endif + +SIMDE_FUNCTION_ATTRIBUTES +unsigned int +SIMDE_MM_GET_ROUNDING_MODE(void) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _MM_GET_ROUNDING_MODE(); + #elif defined(SIMDE_HAVE_FENV_H) + unsigned int vfe_mode; + + switch (fegetround()) { + #if defined(FE_TONEAREST) + case FE_TONEAREST: + vfe_mode = SIMDE_MM_ROUND_NEAREST; + break; + #endif + + #if defined(FE_TOWARDZERO) + case FE_TOWARDZERO: + vfe_mode = SIMDE_MM_ROUND_DOWN; + break; + #endif + + #if defined(FE_UPWARD) + case FE_UPWARD: + vfe_mode = SIMDE_MM_ROUND_UP; + break; + #endif + + #if defined(FE_DOWNWARD) + case FE_DOWNWARD: + vfe_mode = SIMDE_MM_ROUND_TOWARD_ZERO; + break; + #endif + + default: + vfe_mode = SIMDE_MM_ROUND_NEAREST; + break; + } + + return vfe_mode; + #else + return SIMDE_MM_ROUND_NEAREST; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_GET_ROUNDING_MODE() SIMDE_MM_GET_ROUNDING_MODE() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +SIMDE_MM_SET_ROUNDING_MODE(unsigned int a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _MM_SET_ROUNDING_MODE(a); + #elif defined(SIMDE_HAVE_FENV_H) + int fe_mode = FE_TONEAREST; + + switch (a) { + #if defined(FE_TONEAREST) + case SIMDE_MM_ROUND_NEAREST: + fe_mode = FE_TONEAREST; + break; + #endif + + #if defined(FE_TOWARDZERO) + case SIMDE_MM_ROUND_TOWARD_ZERO: + fe_mode = FE_TOWARDZERO; + break; + #endif + + #if defined(FE_DOWNWARD) + case SIMDE_MM_ROUND_DOWN: + fe_mode = FE_DOWNWARD; + break; + #endif + + #if defined(FE_UPWARD) + case SIMDE_MM_ROUND_UP: + fe_mode = FE_UPWARD; + break; + #endif + + default: + return; + } + + fesetround(fe_mode); + #else + (void) a; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_SET_ROUNDING_MODE(a) SIMDE_MM_SET_ROUNDING_MODE(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +uint32_t +SIMDE_MM_GET_FLUSH_ZERO_MODE (void) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_getcsr() & _MM_FLUSH_ZERO_MASK; + #else + return SIMDE_MM_FLUSH_ZERO_OFF; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_SET_FLUSH_ZERO_MODE(a) SIMDE_MM_SET_FLUSH_ZERO_MODE(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +SIMDE_MM_SET_FLUSH_ZERO_MODE (uint32_t a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _MM_SET_FLUSH_ZERO_MODE(a); + #else + (void) a; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _MM_SET_FLUSH_ZERO_MODE(a) SIMDE_MM_SET_FLUSH_ZERO_MODE(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +uint32_t +simde_mm_getcsr (void) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_getcsr(); + #else + return SIMDE_MM_GET_ROUNDING_MODE(); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _mm_getcsr() simde_mm_getcsr() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_setcsr (uint32_t a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_setcsr(a); + #else + SIMDE_MM_SET_ROUNDING_MODE(HEDLEY_STATIC_CAST(unsigned int, a)); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _mm_setcsr(a) simde_mm_setcsr(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_round_ps (simde__m128 a, int rounding, int lax_rounding) + SIMDE_REQUIRE_CONSTANT_RANGE(rounding, 0, 15) + SIMDE_REQUIRE_CONSTANT_RANGE(lax_rounding, 0, 1) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + (void) lax_rounding; + + /* For architectures which lack a current direction SIMD instruction. + * + * Note that NEON actually has a current rounding mode instruction, + * but in ARMv8+ the rounding mode is ignored and nearest is always + * used, so we treat ARMv7 as having a rounding mode but ARMv8 as + * not. */ + #if \ + defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || \ + defined(SIMDE_ARM_NEON_A32V8) + if ((rounding & 7) == SIMDE_MM_FROUND_CUR_DIRECTION) + rounding = HEDLEY_STATIC_CAST(int, SIMDE_MM_GET_ROUNDING_MODE()) << 13; + #endif + + switch (rounding & ~SIMDE_MM_FROUND_NO_EXC) { + case SIMDE_MM_FROUND_CUR_DIRECTION: + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_round(a_.altivec_f32)); + #elif defined(SIMDE_ARM_NEON_A32V8_NATIVE) && !defined(SIMDE_BUG_GCC_95399) + r_.neon_f32 = vrndiq_f32(a_.neon_f32); + #elif defined(simde_math_nearbyintf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_nearbyintf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_NEAREST_INT: + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_rint(a_.altivec_f32)); + #elif defined(SIMDE_ARM_NEON_A32V8_NATIVE) + r_.neon_f32 = vrndnq_f32(a_.neon_f32); + #elif defined(simde_math_roundevenf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_roundevenf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_NEG_INF: + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_floor(a_.altivec_f32)); + #elif defined(SIMDE_ARM_NEON_A32V8_NATIVE) + r_.neon_f32 = vrndmq_f32(a_.neon_f32); + #elif defined(simde_math_floorf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_floorf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_POS_INF: + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_ceil(a_.altivec_f32)); + #elif defined(SIMDE_ARM_NEON_A32V8_NATIVE) + r_.neon_f32 = vrndpq_f32(a_.neon_f32); + #elif defined(simde_math_ceilf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_ceilf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_ZERO: + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_trunc(a_.altivec_f32)); + #elif defined(SIMDE_ARM_NEON_A32V8_NATIVE) + r_.neon_f32 = vrndq_f32(a_.neon_f32); + #elif defined(simde_math_truncf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_truncf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + default: + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) + #define simde_mm_round_ps(a, rounding) _mm_round_ps((a), (rounding)) +#else + #define simde_mm_round_ps(a, rounding) simde_x_mm_round_ps((a), (rounding), 0) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #define _mm_round_ps(a, rounding) simde_mm_round_ps((a), (rounding)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_set_ps (simde_float32 e3, simde_float32 e2, simde_float32 e1, simde_float32 e0) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_set_ps(e3, e2, e1, e0); + #else + simde__m128_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_TO_16 simde_float32 data[4] = { e0, e1, e2, e3 }; + r_.neon_f32 = vld1q_f32(data); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_make(e0, e1, e2, e3); + #else + r_.f32[0] = e0; + r_.f32[1] = e1; + r_.f32[2] = e2; + r_.f32[3] = e3; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_set_ps(e3, e2, e1, e0) simde_mm_set_ps(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_set_ps1 (simde_float32 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_set_ps1(a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vdupq_n_f32(a); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + (void) a; + return vec_splats(a); + #else + return simde_mm_set_ps(a, a, a, a); + #endif +} +#define simde_mm_set1_ps(a) simde_mm_set_ps1(a) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_set_ps1(a) simde_mm_set_ps1(a) +# define _mm_set1_ps(a) simde_mm_set1_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_move_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_move_ss(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsetq_lane_f32(vgetq_lane_f32(b_.neon_f32, 0), a_.neon_f32, 0); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) m = { + 16, 17, 18, 19, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15 + }; + r_.altivec_f32 = vec_perm(a_.altivec_f32, b_.altivec_f32, m); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v8x16_shuffle(b_.wasm_v128, a_.wasm_v128, 0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 4, 1, 2, 3); + #else + r_.f32[0] = b_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_move_ss(a, b) simde_mm_move_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_add_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_add_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vaddq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_add(a_.altivec_f32, b_.altivec_f32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 + b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] + b_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_add_ps(a, b) simde_mm_add_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_add_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_add_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_add_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32_t b0 = vgetq_lane_f32(b_.neon_f32, 0); + float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0); + // the upper values in the result must be the remnants of . + r_.neon_f32 = vaddq_f32(a_.neon_f32, value); + #else + r_.f32[0] = a_.f32[0] + b_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_add_ss(a, b) simde_mm_add_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_and_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_and_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vandq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_and(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 & b_.i32; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_and(a_.altivec_f32, b_.altivec_f32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] & b_.i32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_and_ps(a, b) simde_mm_and_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_andnot_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_andnot_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vbicq_s32(b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_andnot(b_.wasm_v128, a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = vec_andc(b_.altivec_f32, a_.altivec_f32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = ~a_.i32 & b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = ~(a_.i32[i]) & b_.i32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_andnot_ps(a, b) simde_mm_andnot_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_xor_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_xor_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = veorq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_xor(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_xor(a_.altivec_i32, b_.altivec_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] ^ b_.u32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_xor_ps(a, b) simde_mm_xor_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_or_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_or_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vorrq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_or(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_or(a_.altivec_i32, b_.altivec_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f | b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] | b_.u32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_or_ps(a, b) simde_mm_or_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_not_ps(simde__m128 a) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) + __m128i ai = _mm_castps_si128(a); + return _mm_castsi128_ps(_mm_ternarylogic_epi32(ai, ai, ai, 0x55)); + #elif defined(SIMDE_X86_SSE2_NATIVE) + /* Note: we use ints instead of floats because we don't want cmpeq + * to return false for (NaN, NaN) */ + __m128i ai = _mm_castps_si128(a); + return _mm_castsi128_ps(_mm_andnot_si128(ai, _mm_cmpeq_epi32(ai, ai))); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vmvnq_s32(a_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_nor(a_.altivec_i32, a_.altivec_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_not(a_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = ~a_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = ~(a_.i32[i]); + } + #endif + + return simde__m128_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_select_ps(simde__m128 a, simde__m128 b, simde__m128 mask) { + /* This function is for when you want to blend two elements together + * according to a mask. It is similar to _mm_blendv_ps, except that + * it is undefined whether the blend is based on the highest bit in + * each lane (like blendv) or just bitwise operations. This allows + * us to implement the function efficiently everywhere. + * + * Basically, you promise that all the lanes in mask are either 0 or + * ~0. */ + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_blendv_ps(a, b, mask); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b), + mask_ = simde__m128_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vbslq_s32(mask_.neon_u32, b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_bitselect(b_.wasm_v128, a_.wasm_v128, mask_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_sel(a_.altivec_i32, b_.altivec_i32, mask_.altivec_u32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 ^ ((a_.i32 ^ b_.i32) & mask_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] ^ ((a_.i32[i] ^ b_.i32[i]) & mask_.i32[i]); + } + #endif + + return simde__m128_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_avg_pu16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_avg_pu16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vrhadd_u16(b_.neon_u16, a_.neon_u16); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) && defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_CONVERT_VECTOR_) + uint32_t wa SIMDE_VECTOR(16); + uint32_t wb SIMDE_VECTOR(16); + uint32_t wr SIMDE_VECTOR(16); + SIMDE_CONVERT_VECTOR_(wa, a_.u16); + SIMDE_CONVERT_VECTOR_(wb, b_.u16); + wr = (wa + wb + 1) >> 1; + SIMDE_CONVERT_VECTOR_(r_.u16, wr); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = (a_.u16[i] + b_.u16[i] + 1) >> 1; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pavgw(a, b) simde_mm_avg_pu16(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_avg_pu16(a, b) simde_mm_avg_pu16(a, b) +# define _m_pavgw(a, b) simde_mm_avg_pu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_avg_pu8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_avg_pu8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vrhadd_u8(b_.neon_u8, a_.neon_u8); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) && defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_CONVERT_VECTOR_) + uint16_t wa SIMDE_VECTOR(16); + uint16_t wb SIMDE_VECTOR(16); + uint16_t wr SIMDE_VECTOR(16); + SIMDE_CONVERT_VECTOR_(wa, a_.u8); + SIMDE_CONVERT_VECTOR_(wb, b_.u8); + wr = (wa + wb + 1) >> 1; + SIMDE_CONVERT_VECTOR_(r_.u8, wr); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] + b_.u8[i] + 1) >> 1; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pavgb(a, b) simde_mm_avg_pu8(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_avg_pu8(a, b) simde_mm_avg_pu8(a, b) +# define _m_pavgb(a, b) simde_mm_avg_pu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_abs_ps(simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + simde_float32 mask_; + uint32_t u32_ = UINT32_C(0x7FFFFFFF); + simde_memcpy(&mask_, &u32_, sizeof(u32_)); + return _mm_and_ps(_mm_set1_ps(mask_), a); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vabsq_f32(a_.neon_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = vec_abs(a_.altivec_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_abs(a_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_fabsf(a_.f32[i]); + } + #endif + + return simde__m128_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpeq_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpeq_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vceqq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_eq(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmpeq(a_.altivec_f32, b_.altivec_f32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), a_.f32 == b_.f32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (a_.f32[i] == b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpeq_ps(a, b) simde_mm_cmpeq_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpeq_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpeq_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmpeq_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.u32[0] = (a_.f32[0] == b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpeq_ss(a, b) simde_mm_cmpeq_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpge_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpge_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcgeq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_ge(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmpge(a_.altivec_f32, b_.altivec_f32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 >= b_.f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (a_.f32[i] >= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpge_ps(a, b) simde_mm_cmpge_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpge_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && !defined(__PGI) + return _mm_cmpge_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmpge_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.u32[0] = (a_.f32[0] >= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpge_ss(a, b) simde_mm_cmpge_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpgt_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpgt_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcgtq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_gt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmpgt(a_.altivec_f32, b_.altivec_f32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 > b_.f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (a_.f32[i] > b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpgt_ps(a, b) simde_mm_cmpgt_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpgt_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && !defined(__PGI) + return _mm_cmpgt_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmpgt_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.u32[0] = (a_.f32[0] > b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpgt_ss(a, b) simde_mm_cmpgt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmple_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmple_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcleq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_le(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmple(a_.altivec_f32, b_.altivec_f32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 <= b_.f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (a_.f32[i] <= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmple_ps(a, b) simde_mm_cmple_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmple_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmple_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmple_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.u32[0] = (a_.f32[0] <= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmple_ss(a, b) simde_mm_cmple_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmplt_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmplt_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcltq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_lt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmplt(a_.altivec_f32, b_.altivec_f32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 < b_.f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (a_.f32[i] < b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmplt_ps(a, b) simde_mm_cmplt_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmplt_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmplt_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmplt_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.u32[0] = (a_.f32[0] < b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmplt_ss(a, b) simde_mm_cmplt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpneq_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpneq_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vmvnq_u32(vceqq_f32(a_.neon_f32, b_.neon_f32)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_ne(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P9_NATIVE) && SIMDE_ARCH_POWER_CHECK(900) && !defined(HEDLEY_IBM_VERSION) + /* vec_cmpne(SIMDE_POWER_ALTIVEC_VECTOR(float), SIMDE_POWER_ALTIVEC_VECTOR(float)) + is missing from XL C/C++ v16.1.1, + though the documentation (table 89 on page 432 of the IBM XL C/C++ for + Linux Compiler Reference, Version 16.1.1) shows that it should be + present. Both GCC and clang support it. */ + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmpne(a_.altivec_f32, b_.altivec_f32)); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_cmpeq(a_.altivec_f32, b_.altivec_f32)); + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), vec_nor(r_.altivec_f32, r_.altivec_f32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 != b_.f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (a_.f32[i] != b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpneq_ps(a, b) simde_mm_cmpneq_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpneq_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpneq_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmpneq_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.u32[0] = (a_.f32[0] != b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpneq_ss(a, b) simde_mm_cmpneq_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpnge_ps (simde__m128 a, simde__m128 b) { + return simde_mm_cmplt_ps(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpnge_ps(a, b) simde_mm_cmpnge_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpnge_ss (simde__m128 a, simde__m128 b) { + return simde_mm_cmplt_ss(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpnge_ss(a, b) simde_mm_cmpnge_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpngt_ps (simde__m128 a, simde__m128 b) { + return simde_mm_cmple_ps(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpngt_ps(a, b) simde_mm_cmpngt_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpngt_ss (simde__m128 a, simde__m128 b) { + return simde_mm_cmple_ss(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpngt_ss(a, b) simde_mm_cmpngt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpnle_ps (simde__m128 a, simde__m128 b) { + return simde_mm_cmpgt_ps(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpnle_ps(a, b) simde_mm_cmpnle_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpnle_ss (simde__m128 a, simde__m128 b) { + return simde_mm_cmpgt_ss(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpnle_ss(a, b) simde_mm_cmpnle_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpnlt_ps (simde__m128 a, simde__m128 b) { + return simde_mm_cmpge_ps(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpnlt_ps(a, b) simde_mm_cmpnlt_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpnlt_ss (simde__m128 a, simde__m128 b) { + return simde_mm_cmpge_ss(a, b); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpnlt_ss(a, b) simde_mm_cmpnlt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpord_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpord_ps(a, b); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_v128_and(wasm_f32x4_eq(a, a), wasm_f32x4_eq(b, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* Note: NEON does not have ordered compare builtin + Need to compare a eq a and b eq b to check for NaN + Do AND of results to get final */ + uint32x4_t ceqaa = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t ceqbb = vceqq_f32(b_.neon_f32, b_.neon_f32); + r_.neon_u32 = vandq_u32(ceqaa, ceqbb); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_and(wasm_f32x4_eq(a_.wasm_v128, a_.wasm_v128), wasm_f32x4_eq(b_.wasm_v128, b_.wasm_v128)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), + vec_and(vec_cmpeq(a_.altivec_f32, a_.altivec_f32), vec_cmpeq(b_.altivec_f32, b_.altivec_f32))); + #elif defined(simde_math_isnanf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? UINT32_C(0) : ~UINT32_C(0); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpord_ps(a, b) simde_mm_cmpord_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpunord_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpunord_ps(a, b); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_v128_or(wasm_f32x4_ne(a, a), wasm_f32x4_ne(b, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t ceqaa = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t ceqbb = vceqq_f32(b_.neon_f32, b_.neon_f32); + r_.neon_u32 = vmvnq_u32(vandq_u32(ceqaa, ceqbb)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_or(wasm_f32x4_ne(a_.wasm_v128, a_.wasm_v128), wasm_f32x4_ne(b_.wasm_v128, b_.wasm_v128)); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), + vec_nand(vec_cmpeq(a_.altivec_f32, a_.altivec_f32), vec_cmpeq(b_.altivec_f32, b_.altivec_f32))); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), + vec_and(vec_cmpeq(a_.altivec_f32, a_.altivec_f32), vec_cmpeq(b_.altivec_f32, b_.altivec_f32))); + r_.altivec_f32 = vec_nor(r_.altivec_f32, r_.altivec_f32); + #elif defined(simde_math_isnanf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpunord_ps(a, b) simde_mm_cmpunord_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpunord_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && !defined(__PGI) + return _mm_cmpunord_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmpunord_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(simde_math_isnanf) + r_.u32[0] = (simde_math_isnanf(a_.f32[0]) || simde_math_isnanf(b_.f32[0])) ? ~UINT32_C(0) : UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpunord_ss(a, b) simde_mm_cmpunord_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comieq_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_comieq_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_eq_b = vceqq_f32(a_.neon_f32, b_.neon_f32); + return !!(vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_eq_b), 0) != 0); + #else + return a_.f32[0] == b_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_comieq_ss(a, b) simde_mm_comieq_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comige_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_comige_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_ge_b = vcgeq_f32(a_.neon_f32, b_.neon_f32); + return !!(vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_ge_b), 0) != 0); + #else + return a_.f32[0] >= b_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_comige_ss(a, b) simde_mm_comige_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comigt_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_comigt_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_gt_b = vcgtq_f32(a_.neon_f32, b_.neon_f32); + return !!(vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_gt_b), 0) != 0); + #else + return a_.f32[0] > b_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_comigt_ss(a, b) simde_mm_comigt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comile_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_comile_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_le_b = vcleq_f32(a_.neon_f32, b_.neon_f32); + return !!(vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_le_b), 0) != 0); + #else + return a_.f32[0] <= b_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_comile_ss(a, b) simde_mm_comile_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comilt_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_comilt_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_lt_b = vcltq_f32(a_.neon_f32, b_.neon_f32); + return !!(vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_lt_b), 0) != 0); + #else + return a_.f32[0] < b_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_comilt_ss(a, b) simde_mm_comilt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comineq_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_comineq_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_neq_b = vmvnq_u32(vceqq_f32(a_.neon_f32, b_.neon_f32)); + return !!(vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_neq_b), 0) != 0); + #else + return a_.f32[0] != b_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_comineq_ss(a, b) simde_mm_comineq_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_copysign_ps(simde__m128 dest, simde__m128 src) { + simde__m128_private + r_, + dest_ = simde__m128_to_private(dest), + src_ = simde__m128_to_private(src); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const uint32x4_t sign_pos = vreinterpretq_u32_f32(vdupq_n_f32(-SIMDE_FLOAT32_C(0.0))); + r_.neon_u32 = vbslq_u32(sign_pos, src_.neon_u32, dest_.neon_u32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + const v128_t sign_pos = wasm_f32x4_splat(-0.0f); + r_.wasm_v128 = wasm_v128_bitselect(src_.wasm_v128, dest_.wasm_v128, sign_pos); + #elif defined(SIMDE_POWER_ALTIVEC_P9_NATIVE) + #if !defined(HEDLEY_IBM_VERSION) + r_.altivec_f32 = vec_cpsgn(dest_.altivec_f32, src_.altivec_f32); + #else + r_.altivec_f32 = vec_cpsgn(src_.altivec_f32, dest_.altivec_f32); + #endif + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + const SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) sign_pos = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned int), vec_splats(-0.0f)); + r_.altivec_f32 = vec_sel(dest_.altivec_f32, src_.altivec_f32, sign_pos); + #elif defined(SIMDE_IEEE754_STORAGE) + (void) src_; + (void) dest_; + simde__m128 sign_pos = simde_mm_set1_ps(-0.0f); + r_ = simde__m128_to_private(simde_mm_xor_ps(dest, simde_mm_and_ps(simde_mm_xor_ps(dest, src), sign_pos))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_copysignf(dest_.f32[i], src_.f32[i]); + } + #endif + + return simde__m128_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_xorsign_ps(simde__m128 dest, simde__m128 src) { + return simde_mm_xor_ps(simde_mm_and_ps(simde_mm_set1_ps(-0.0f), src), dest); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvt_pi2ps (simde__m128 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvt_pi2ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcombine_f32(vcvt_f32_s32(b_.neon_i32), vget_high_f32(a_.neon_f32)); + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.m64_private[0].f32, b_.i32); + r_.m64_private[1] = a_.m64_private[1]; + #else + r_.f32[0] = (simde_float32) b_.i32[0]; + r_.f32[1] = (simde_float32) b_.i32[1]; + r_.i32[2] = a_.i32[2]; + r_.i32[3] = a_.i32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvt_pi2ps(a, b) simde_mm_cvt_pi2ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvt_ps2pi (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvt_ps2pi(a); + #else + simde__m64_private r_; + simde__m128_private a_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + a_ = simde__m128_to_private(simde_mm_round_ps(a, SIMDE_MM_FROUND_CUR_DIRECTION)); + r_.neon_i32 = vcvt_s32_f32(vget_low_f32(a_.neon_f32)); + #elif defined(SIMDE_CONVERT_VECTOR_) && SIMDE_NATURAL_VECTOR_SIZE_GE(128) + a_ = simde__m128_to_private(simde_mm_round_ps(a, SIMDE_MM_FROUND_CUR_DIRECTION)); + SIMDE_CONVERT_VECTOR_(r_.i32, a_.m64_private[0].f32); + #else + a_ = simde__m128_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = HEDLEY_STATIC_CAST(int32_t, simde_math_nearbyintf(a_.f32[i])); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvt_ps2pi(a) simde_mm_cvt_ps2pi((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvt_si2ss (simde__m128 a, int32_t b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cvt_si2ss(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsetq_lane_f32(HEDLEY_STATIC_CAST(float, b), a_.neon_f32, 0); + #else + r_.f32[0] = HEDLEY_STATIC_CAST(simde_float32, b); + r_.i32[1] = a_.i32[1]; + r_.i32[2] = a_.i32[2]; + r_.i32[3] = a_.i32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvt_si2ss(a, b) simde_mm_cvt_si2ss((a), b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvt_ss2si (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cvt_ss2si(a); + #elif defined(SIMDE_ARM_NEON_A32V8_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) && !defined(SIMDE_BUG_GCC_95399) + return vgetq_lane_s32(vcvtnq_s32_f32(simde__m128_to_neon_f32(a)), 0); + #else + simde__m128_private a_ = simde__m128_to_private(simde_mm_round_ps(a, SIMDE_MM_FROUND_CUR_DIRECTION)); + #if !defined(SIMDE_FAST_CONVERSION_RANGE) + return ((a_.f32[0] > HEDLEY_STATIC_CAST(simde_float32, INT32_MIN)) && + (a_.f32[0] < HEDLEY_STATIC_CAST(simde_float32, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, a_.f32[0]) : INT32_MIN; + #else + return SIMDE_CONVERT_FTOI(int32_t, a_.f32[0]); + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvt_ss2si(a) simde_mm_cvt_ss2si((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpi16_ps (simde__m64 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpi16_ps(a); + #else + simde__m128_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcvtq_f32_s32(vmovl_s16(a_.neon_i16)); + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.f32, a_.i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + simde_float32 v = a_.i16[i]; + r_.f32[i] = v; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtpi16_ps(a) simde_mm_cvtpi16_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpi32_ps (simde__m128 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpi32_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + simde__m64_private b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcombine_f32(vcvt_f32_s32(b_.neon_i32), vget_high_f32(a_.neon_f32)); + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.m64_private[0].f32, b_.i32); + r_.m64_private[1] = a_.m64_private[1]; + #else + r_.f32[0] = (simde_float32) b_.i32[0]; + r_.f32[1] = (simde_float32) b_.i32[1]; + r_.i32[2] = a_.i32[2]; + r_.i32[3] = a_.i32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtpi32_ps(a, b) simde_mm_cvtpi32_ps((a), b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpi32x2_ps (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpi32x2_ps(a, b); + #else + simde__m128_private r_; + simde__m64_private + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcvtq_f32_s32(vcombine_s32(a_.neon_i32, b_.neon_i32)); + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.m64_private[0].f32, a_.i32); + SIMDE_CONVERT_VECTOR_(r_.m64_private[1].f32, b_.i32); + #else + r_.f32[0] = (simde_float32) a_.i32[0]; + r_.f32[1] = (simde_float32) a_.i32[1]; + r_.f32[2] = (simde_float32) b_.i32[0]; + r_.f32[3] = (simde_float32) b_.i32[1]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtpi32x2_ps(a, b) simde_mm_cvtpi32x2_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpi8_ps (simde__m64 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpi8_ps(a); + #else + simde__m128_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcvtq_f32_s32(vmovl_s16(vget_low_s16(vmovl_s8(a_.neon_i8)))); + #else + r_.f32[0] = HEDLEY_STATIC_CAST(simde_float32, a_.i8[0]); + r_.f32[1] = HEDLEY_STATIC_CAST(simde_float32, a_.i8[1]); + r_.f32[2] = HEDLEY_STATIC_CAST(simde_float32, a_.i8[2]); + r_.f32[3] = HEDLEY_STATIC_CAST(simde_float32, a_.i8[3]); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtpi8_ps(a) simde_mm_cvtpi8_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtps_pi16 (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtps_pi16(a); + #else + simde__m64_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V8_NATIVE) && !defined(SIMDE_BUG_GCC_95399) + r_.neon_i16 = vmovn_s32(vcvtq_s32_f32(vrndiq_f32(a_.neon_f32))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = SIMDE_CONVERT_FTOI(int16_t, simde_math_roundf(a_.f32[i])); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtps_pi16(a) simde_mm_cvtps_pi16((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtps_pi32 (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtps_pi32(a); + #else + simde__m64_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V8_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) && !defined(SIMDE_BUG_GCC_95399) + r_.neon_i32 = vcvt_s32_f32(vget_low_f32(vrndiq_f32(a_.neon_f32))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + simde_float32 v = simde_math_roundf(a_.f32[i]); + #if !defined(SIMDE_FAST_CONVERSION_RANGE) + r_.i32[i] = ((v > HEDLEY_STATIC_CAST(simde_float32, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float32, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #else + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, v); + #endif + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtps_pi32(a) simde_mm_cvtps_pi32((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtps_pi8 (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtps_pi8(a); + #else + simde__m64_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V8_NATIVE) && !defined(SIMDE_BUG_GCC_95471) + /* Clamp the input to [INT8_MIN, INT8_MAX], round, convert to i32, narrow to + * i16, combine with an all-zero vector of i16 (which will become the upper + * half), narrow to i8. */ + float32x4_t max = vdupq_n_f32(HEDLEY_STATIC_CAST(simde_float32, INT8_MAX)); + float32x4_t min = vdupq_n_f32(HEDLEY_STATIC_CAST(simde_float32, INT8_MIN)); + float32x4_t values = vrndnq_f32(vmaxq_f32(vminq_f32(max, a_.neon_f32), min)); + r_.neon_i8 = vmovn_s16(vcombine_s16(vmovn_s32(vcvtq_s32_f32(values)), vdup_n_s16(0))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + if (a_.f32[i] > HEDLEY_STATIC_CAST(simde_float32, INT8_MAX)) + r_.i8[i] = INT8_MAX; + else if (a_.f32[i] < HEDLEY_STATIC_CAST(simde_float32, INT8_MIN)) + r_.i8[i] = INT8_MIN; + else + r_.i8[i] = SIMDE_CONVERT_FTOI(int8_t, simde_math_roundf(a_.f32[i])); + } + /* Note: the upper half is undefined */ + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtps_pi8(a) simde_mm_cvtps_pi8((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpu16_ps (simde__m64 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpu16_ps(a); + #else + simde__m128_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcvtq_f32_u32(vmovl_u16(a_.neon_u16)); + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.f32, a_.u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (simde_float32) a_.u16[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtpu16_ps(a) simde_mm_cvtpu16_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpu8_ps (simde__m64 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpu8_ps(a); + #else + simde__m128_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcvtq_f32_u32(vmovl_u16(vget_low_u16(vmovl_u8(a_.neon_u8)))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = HEDLEY_STATIC_CAST(simde_float32, a_.u8[i]); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtpu8_ps(a) simde_mm_cvtpu8_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtsi32_ss (simde__m128 a, int32_t b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cvtsi32_ss(a, b); + #else + simde__m128_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsetq_lane_f32(HEDLEY_STATIC_CAST(float32_t, b), a_.neon_f32, 0); + #else + r_ = a_; + r_.f32[0] = HEDLEY_STATIC_CAST(simde_float32, b); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtsi32_ss(a, b) simde_mm_cvtsi32_ss((a), b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtsi64_ss (simde__m128 a, int64_t b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if !defined(__PGI) + return _mm_cvtsi64_ss(a, b); + #else + return _mm_cvtsi64x_ss(a, b); + #endif + #else + simde__m128_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsetq_lane_f32(HEDLEY_STATIC_CAST(float32_t, b), a_.neon_f32, 0); + #else + r_ = a_; + r_.f32[0] = HEDLEY_STATIC_CAST(simde_float32, b); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) +# define _mm_cvtsi64_ss(a, b) simde_mm_cvtsi64_ss((a), b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde_float32 +simde_mm_cvtss_f32 (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cvtss_f32(a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vgetq_lane_f32(a_.neon_f32, 0); + #else + return a_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtss_f32(a) simde_mm_cvtss_f32((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvtss_si32 (simde__m128 a) { + return simde_mm_cvt_ss2si(a); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtss_si32(a) simde_mm_cvtss_si32((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_cvtss_si64 (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if !defined(__PGI) + return _mm_cvtss_si64(a); + #else + return _mm_cvtss_si64x(a); + #endif + #else + simde__m128_private a_ = simde__m128_to_private(a); + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return SIMDE_CONVERT_FTOI(int64_t, simde_math_roundf(vgetq_lane_f32(a_.neon_f32, 0))); + #else + return SIMDE_CONVERT_FTOI(int64_t, simde_math_roundf(a_.f32[0])); + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) +# define _mm_cvtss_si64(a) simde_mm_cvtss_si64((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtt_ps2pi (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtt_ps2pi(a); + #else + simde__m64_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) + r_.neon_i32 = vcvt_s32_f32(vget_low_f32(a_.neon_f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + simde_float32 v = a_.f32[i]; + #if !defined(SIMDE_FAST_CONVERSION_RANGE) + r_.i32[i] = ((v > HEDLEY_STATIC_CAST(simde_float32, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float32, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #else + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, v); + #endif + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_mm_cvttps_pi32(a) simde_mm_cvtt_ps2pi(a) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtt_ps2pi(a) simde_mm_cvtt_ps2pi((a)) +# define _mm_cvttps_pi32(a) simde_mm_cvttps_pi32((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvtt_ss2si (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cvtt_ss2si(a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) + return SIMDE_CONVERT_FTOI(int32_t, vgetq_lane_f32(a_.neon_f32, 0)); + #else + simde_float32 v = a_.f32[0]; + #if !defined(SIMDE_FAST_CONVERSION_RANGE) + return ((v > HEDLEY_STATIC_CAST(simde_float32, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float32, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #else + return SIMDE_CONVERT_FTOI(int32_t, v); + #endif + #endif + #endif +} +#define simde_mm_cvttss_si32(a) simde_mm_cvtt_ss2si((a)) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cvtt_ss2si(a) simde_mm_cvtt_ss2si((a)) +# define _mm_cvttss_si32(a) simde_mm_cvtt_ss2si((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_cvttss_si64 (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_ARCH_AMD64) && !defined(_MSC_VER) + #if defined(__PGI) + return _mm_cvttss_si64x(a); + #else + return _mm_cvttss_si64(a); + #endif + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return SIMDE_CONVERT_FTOI(int64_t, vgetq_lane_f32(a_.neon_f32, 0)); + #else + return SIMDE_CONVERT_FTOI(int64_t, a_.f32[0]); + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) +# define _mm_cvttss_si64(a) simde_mm_cvttss_si64((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmpord_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_cmpord_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_cmpord_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(simde_math_isnanf) + r_.u32[0] = (simde_math_isnanf(simde_mm_cvtss_f32(a)) || simde_math_isnanf(simde_mm_cvtss_f32(b))) ? UINT32_C(0) : ~UINT32_C(0); + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = a_.u32[i]; + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_cmpord_ss(a, b) simde_mm_cmpord_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_div_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_div_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vdivq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4_t recip0 = vrecpeq_f32(b_.neon_f32); + float32x4_t recip1 = vmulq_f32(recip0, vrecpsq_f32(recip0, b_.neon_f32)); + r_.neon_f32 = vmulq_f32(a_.neon_f32, recip1); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_div(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + r_.altivec_f32 = vec_div(a_.altivec_f32, b_.altivec_f32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 / b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] / b_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_div_ps(a, b) simde_mm_div_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_div_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_div_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_div_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32_t value = + vgetq_lane_f32(simde__m128_to_private(simde_mm_div_ps(a, b)).neon_f32, 0); + r_.neon_f32 = vsetq_lane_f32(value, a_.neon_f32, 0); + #else + r_.f32[0] = a_.f32[0] / b_.f32[0]; + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_div_ss(a, b) simde_mm_div_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int16_t +simde_mm_extract_pi16 (simde__m64 a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m64_private a_ = simde__m64_to_private(a); + return a_.i16[imm8]; +} +#if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) && !defined(HEDLEY_PGI_VERSION) +# if defined(SIMDE_BUG_CLANG_44589) +# define simde_mm_extract_pi16(a, imm8) ( \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wvector-conversion\"") \ + HEDLEY_STATIC_CAST(int16_t, _mm_extract_pi16((a), (imm8))) \ + HEDLEY_DIAGNOSTIC_POP \ + ) +# else +# define simde_mm_extract_pi16(a, imm8) HEDLEY_STATIC_CAST(int16_t, _mm_extract_pi16(a, imm8)) +# endif +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_extract_pi16(a, imm8) vget_lane_s16(simde__m64_to_private(a).neon_i16, imm8) +#endif +#define simde_m_pextrw(a, imm8) simde_mm_extract_pi16(a, imm8) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_extract_pi16(a, imm8) simde_mm_extract_pi16((a), (imm8)) +# define _m_pextrw(a, imm8) simde_mm_extract_pi16((a), (imm8)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_insert_pi16 (simde__m64 a, int16_t i, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m64_private + r_, + a_ = simde__m64_to_private(a); + + r_.i64[0] = a_.i64[0]; + r_.i16[imm8] = i; + + return simde__m64_from_private(r_); +} +#if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) +# if defined(SIMDE_BUG_CLANG_44589) +# define ssimde_mm_insert_pi16(a, i, imm8) ( \ + HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wvector-conversion\"") \ + (_mm_insert_pi16((a), (i), (imm8))) \ + HEDLEY_DIAGNOSTIC_POP \ + ) +# else +# define simde_mm_insert_pi16(a, i, imm8) _mm_insert_pi16(a, i, imm8) +# endif +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_insert_pi16(a, i, imm8) simde__m64_from_neon_i16(vset_lane_s16((i), simde__m64_to_neon_i16(a), (imm8))) +#endif +#define simde_m_pinsrw(a, i, imm8) (simde_mm_insert_pi16(a, i, imm8)) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_insert_pi16(a, i, imm8) simde_mm_insert_pi16(a, i, imm8) +# define _m_pinsrw(a, i, imm8) simde_mm_insert_pi16(a, i, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_load_ps (simde_float32 const mem_addr[HEDLEY_ARRAY_PARAM(4)]) { +#if defined(SIMDE_X86_SSE_NATIVE) + return _mm_load_ps(mem_addr); +#else + simde__m128_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vld1q_f32(mem_addr); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + r_.altivec_f32 = vec_vsx_ld(0, mem_addr); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_ld(0, mem_addr); + #else + simde_memcpy(&r_, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m128), sizeof(r_)); + #endif + + return simde__m128_from_private(r_); +#endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_load_ps(mem_addr) simde_mm_load_ps(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_load1_ps (simde_float32 const* mem_addr) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_load_ps1(mem_addr); + #else + simde__m128_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vld1q_dup_f32(mem_addr); + #else + r_ = simde__m128_to_private(simde_mm_set1_ps(*mem_addr)); + #endif + + return simde__m128_from_private(r_); + #endif +} +#define simde_mm_load_ps1(mem_addr) simde_mm_load1_ps(mem_addr) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_load_ps1(mem_addr) simde_mm_load1_ps(mem_addr) +# define _mm_load1_ps(mem_addr) simde_mm_load1_ps(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_load_ss (simde_float32 const* mem_addr) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_load_ss(mem_addr); + #else + simde__m128_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsetq_lane_f32(*mem_addr, vdupq_n_f32(0), 0); + #else + r_.f32[0] = *mem_addr; + r_.i32[1] = 0; + r_.i32[2] = 0; + r_.i32[3] = 0; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_load_ss(mem_addr) simde_mm_load_ss(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_loadh_pi (simde__m128 a, simde__m64 const* mem_addr) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_loadh_pi(a, HEDLEY_REINTERPRET_CAST(__m64 const*, mem_addr)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcombine_f32(vget_low_f32(a_.neon_f32), vld1_f32(HEDLEY_REINTERPRET_CAST(const float32_t*, mem_addr))); + #else + simde__m64_private b_ = *HEDLEY_REINTERPRET_CAST(simde__m64_private const*, mem_addr); + r_.f32[0] = a_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = b_.f32[0]; + r_.f32[3] = b_.f32[1]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #if HEDLEY_HAS_WARNING("-Wold-style-cast") + #define _mm_loadh_pi(a, mem_addr) simde_mm_loadh_pi((a), HEDLEY_REINTERPRET_CAST(simde__m64 const*, (mem_addr))) + #else + #define _mm_loadh_pi(a, mem_addr) simde_mm_loadh_pi((a), (simde__m64 const*) (mem_addr)) + #endif +#endif + +/* The SSE documentation says that there are no alignment requirements + for mem_addr. Unfortunately they used the __m64 type for the argument + which is supposed to be 8-byte aligned, so some compilers (like clang + with -Wcast-align) will generate a warning if you try to cast, say, + a simde_float32* to a simde__m64* for this function. + + I think the choice of argument type is unfortunate, but I do think we + need to stick to it here. If there is demand I can always add something + like simde_x_mm_loadl_f32(simde__m128, simde_float32 mem_addr[2]) */ +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_loadl_pi (simde__m128 a, simde__m64 const* mem_addr) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_loadl_pi(a, HEDLEY_REINTERPRET_CAST(__m64 const*, mem_addr)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcombine_f32(vld1_f32( + HEDLEY_REINTERPRET_CAST(const float32_t*, mem_addr)), vget_high_f32(a_.neon_f32)); + #else + simde__m64_private b_; + simde_memcpy(&b_, mem_addr, sizeof(b_)); + r_.i32[0] = b_.i32[0]; + r_.i32[1] = b_.i32[1]; + r_.i32[2] = a_.i32[2]; + r_.i32[3] = a_.i32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #if HEDLEY_HAS_WARNING("-Wold-style-cast") + #define _mm_loadl_pi(a, mem_addr) simde_mm_loadl_pi((a), HEDLEY_REINTERPRET_CAST(simde__m64 const*, (mem_addr))) + #else + #define _mm_loadl_pi(a, mem_addr) simde_mm_loadl_pi((a), (simde__m64 const*) (mem_addr)) + #endif +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_loadr_ps (simde_float32 const mem_addr[HEDLEY_ARRAY_PARAM(4)]) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_loadr_ps(mem_addr); + #else + simde__m128_private + r_, + v_ = simde__m128_to_private(simde_mm_load_ps(mem_addr)); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vrev64q_f32(v_.neon_f32); + r_.neon_f32 = vextq_f32(r_.neon_f32, r_.neon_f32, 2); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) && defined(__PPC64__) + r_.altivec_f32 = vec_reve(v_.altivec_f32); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, v_.f32, v_.f32, 3, 2, 1, 0); + #else + r_.f32[0] = v_.f32[3]; + r_.f32[1] = v_.f32[2]; + r_.f32[2] = v_.f32[1]; + r_.f32[3] = v_.f32[0]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_loadr_ps(mem_addr) simde_mm_loadr_ps(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_loadu_ps (simde_float32 const mem_addr[HEDLEY_ARRAY_PARAM(4)]) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_loadu_ps(mem_addr); + #else + simde__m128_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vld1q_f32(HEDLEY_REINTERPRET_CAST(const float32_t*, mem_addr)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_load(mem_addr); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) && defined(__PPC64__) + r_.altivec_f32 = vec_vsx_ld(0, mem_addr); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_loadu_ps(mem_addr) simde_mm_loadu_ps(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_maskmove_si64 (simde__m64 a, simde__m64 mask, int8_t* mem_addr) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + _mm_maskmove_si64(a, mask, HEDLEY_REINTERPRET_CAST(char*, mem_addr)); + #else + simde__m64_private + a_ = simde__m64_to_private(a), + mask_ = simde__m64_to_private(mask); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.i8) / sizeof(a_.i8[0])) ; i++) + if (mask_.i8[i] < 0) + mem_addr[i] = a_.i8[i]; + #endif +} +#define simde_m_maskmovq(a, mask, mem_addr) simde_mm_maskmove_si64(a, mask, mem_addr) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_maskmove_si64(a, mask, mem_addr) simde_mm_maskmove_si64((a), (mask), SIMDE_CHECKED_REINTERPRET_CAST(int8_t*, char*, (mem_addr))) +# define _m_maskmovq(a, mask, mem_addr) simde_mm_maskmove_si64((a), (mask), SIMDE_CHECKED_REINTERPRET_CAST(int8_t*, char*, (mem_addr))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_max_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_max_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vmax_s16(a_.neon_i16, b_.neon_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] > b_.i16[i]) ? a_.i16[i] : b_.i16[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pmaxsw(a, b) simde_mm_max_pi16(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_max_pi16(a, b) simde_mm_max_pi16(a, b) +# define _m_pmaxsw(a, b) simde_mm_max_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_max_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_max_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) && defined(SIMDE_FAST_NANS) + r_.neon_f32 = vmaxq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vbslq_f32(vcgtq_f32(a_.neon_f32, b_.neon_f32), a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) && defined(SIMDE_FAST_NANS) + r_.wasm_v128 = wasm_f32x4_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_bitselect(a_.wasm_v128, b_.wasm_v128, wasm_f32x4_gt(a_.wasm_v128, b_.wasm_v128)); + #elif (defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE)) && defined(SIMDE_FAST_NANS) + r_.altivec_f32 = vec_max(a_.altivec_f32, b_.altivec_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = vec_sel(b_.altivec_f32, a_.altivec_f32, vec_cmpgt(a_.altivec_f32, b_.altivec_f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (a_.f32[i] > b_.f32[i]) ? a_.f32[i] : b_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_max_ps(a, b) simde_mm_max_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_max_pu8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_max_pu8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vmax_u8(a_.neon_u8, b_.neon_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] > b_.u8[i]) ? a_.u8[i] : b_.u8[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pmaxub(a, b) simde_mm_max_pu8(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_max_pu8(a, b) simde_mm_max_pu8(a, b) +# define _m_pmaxub(a, b) simde_mm_max_pu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_max_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_max_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_max_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32_t value = vgetq_lane_f32(maxq_f32(a_.neon_f32, b_.neon_f32), 0); + r_.neon_f32 = vsetq_lane_f32(value, a_.neon_f32, 0); + #else + r_.f32[0] = (a_.f32[0] > b_.f32[0]) ? a_.f32[0] : b_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_max_ss(a, b) simde_mm_max_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_min_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_min_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vmin_s16(a_.neon_i16, b_.neon_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] < b_.i16[i]) ? a_.i16[i] : b_.i16[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pminsw(a, b) simde_mm_min_pi16(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_min_pi16(a, b) simde_mm_min_pi16(a, b) +# define _m_pminsw(a, b) simde_mm_min_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_min_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_min_ps(a, b); + #elif defined(SIMDE_FAST_NANS) && defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return simde__m128_from_neon_f32(vminq_f32(simde__m128_to_neon_f32(a), simde__m128_to_neon_f32(b))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + #if defined(SIMDE_FAST_NANS) + r_.wasm_v128 = wasm_f32x4_min(a_.wasm_v128, b_.wasm_v128); + #else + r_.wasm_v128 = wasm_v128_bitselect(a_.wasm_v128, b_.wasm_v128, wasm_f32x4_lt(a_.wasm_v128, b_.wasm_v128)); + #endif + return simde__m128_from_private(r_); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_FAST_NANS) + r_.altivec_f32 = vec_min(a_.altivec_f32, b_.altivec_f32); + #else + r_.altivec_f32 = vec_sel(b_.altivec_f32, a_.altivec_f32, vec_cmpgt(b_.altivec_f32, a_.altivec_f32)); + #endif + + return simde__m128_from_private(r_); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + simde__m128 mask = simde_mm_cmplt_ps(a, b); + return simde_mm_or_ps(simde_mm_and_ps(mask, a), simde_mm_andnot_ps(mask, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (a_.f32[i] < b_.f32[i]) ? a_.f32[i] : b_.f32[i]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_min_ps(a, b) simde_mm_min_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_min_pu8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_min_pu8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vmin_u8(a_.neon_u8, b_.neon_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] < b_.u8[i]) ? a_.u8[i] : b_.u8[i]; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pminub(a, b) simde_mm_min_pu8(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_min_pu8(a, b) simde_mm_min_pu8(a, b) +# define _m_pminub(a, b) simde_mm_min_pu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_min_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_min_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_min_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32_t value = vgetq_lane_f32(vminq_f32(a_.neon_f32, b_.neon_f32), 0); + r_.neon_f32 = vsetq_lane_f32(value, a_.neon_f32, 0); + #else + r_.f32[0] = (a_.f32[0] < b_.f32[0]) ? a_.f32[0] : b_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_min_ss(a, b) simde_mm_min_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_movehl_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_movehl_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x2_t a32 = vget_high_f32(a_.neon_f32); + float32x2_t b32 = vget_high_f32(b_.neon_f32); + r_.neon_f32 = vcombine_f32(b32, a32); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), + vec_mergel(b_.altivec_i64, a_.altivec_i64)); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 6, 7, 2, 3); + #else + r_.f32[0] = b_.f32[2]; + r_.f32[1] = b_.f32[3]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_movehl_ps(a, b) simde_mm_movehl_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_movelh_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_movelh_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x2_t a10 = vget_low_f32(a_.neon_f32); + float32x2_t b10 = vget_low_f32(b_.neon_f32); + r_.neon_f32 = vcombine_f32(a10, b10); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 0, 1, 4, 5); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), + vec_mergeh(a_.altivec_i64, b_.altivec_i64)); + #else + r_.f32[0] = a_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = b_.f32[0]; + r_.f32[3] = b_.f32[1]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_movelh_ps(a, b) simde_mm_movelh_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_movemask_pi8 (simde__m64 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_movemask_pi8(a); + #else + simde__m64_private a_ = simde__m64_to_private(a); + int r = 0; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint8x8_t input = a_.neon_u8; + const int8_t xr[8] = {-7, -6, -5, -4, -3, -2, -1, 0}; + const uint8x8_t mask_and = vdup_n_u8(0x80); + const int8x8_t mask_shift = vld1_s8(xr); + const uint8x8_t mask_result = vshl_u8(vand_u8(input, mask_and), mask_shift); + uint8x8_t lo = mask_result; + r = vaddv_u8(lo); + #else + const size_t nmemb = sizeof(a_.i8) / sizeof(a_.i8[0]); + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < nmemb ; i++) { + r |= (a_.u8[nmemb - 1 - i] >> 7) << (nmemb - 1 - i); + } + #endif + + return r; + #endif +} +#define simde_m_pmovmskb(a) simde_mm_movemask_pi8(a) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_movemask_pi8(a) simde_mm_movemask_pi8(a) +# define _m_pmovmskb(a) simde_mm_movemask_pi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_movemask_ps (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_movemask_ps(a); + #else + int r = 0; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + static const int32_t shift_amount[] = { 0, 1, 2, 3 }; + const int32x4_t shift = vld1q_s32(shift_amount); + uint32x4_t tmp = vshrq_n_u32(a_.neon_u32, 31); + return HEDLEY_STATIC_CAST(int, vaddvq_u32(vshlq_u32(tmp, shift))); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + // Shift out everything but the sign bits with a 32-bit unsigned shift right. + uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(a_.neon_u32, 31)); + // Merge the two pairs together with a 64-bit unsigned shift right + add. + uint8x16_t paired = vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31)); + // Extract the result. + return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2); + #else + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < sizeof(a_.u32) / sizeof(a_.u32[0]) ; i++) { + r |= (a_.u32[i] >> ((sizeof(a_.u32[i]) * CHAR_BIT) - 1)) << i; + } + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_movemask_ps(a) simde_mm_movemask_ps((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_mul_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_mul_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vmulq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_mul(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 * b_.f32; + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + r_.altivec_f32 = vec_mul(a_.altivec_f32, b_.altivec_f32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] * b_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_mul_ps(a, b) simde_mm_mul_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_mul_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_mul_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_mul_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.f32[0] = a_.f32[0] * b_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_mul_ss(a, b) simde_mm_mul_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_mulhi_pu16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_mulhi_pu16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const uint32x4_t t1 = vmull_u16(a_.neon_u16, b_.neon_u16); + const uint32x4_t t2 = vshrq_n_u32(t1, 16); + const uint16x4_t t3 = vmovn_u32(t2); + r_.neon_u16 = t3; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, ((HEDLEY_STATIC_CAST(uint32_t, a_.u16[i]) * HEDLEY_STATIC_CAST(uint32_t, b_.u16[i])) >> UINT32_C(16))); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_pmulhuw(a, b) simde_mm_mulhi_pu16(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_mulhi_pu16(a, b) simde_mm_mulhi_pu16(a, b) +# define _m_pmulhuw(a, b) simde_mm_mulhi_pu16(a, b) +#endif + +#if defined(SIMDE_X86_SSE_NATIVE) && defined(HEDLEY_GCC_VERSION) + #define SIMDE_MM_HINT_NTA HEDLEY_STATIC_CAST(enum _mm_hint, 0) + #define SIMDE_MM_HINT_T0 HEDLEY_STATIC_CAST(enum _mm_hint, 1) + #define SIMDE_MM_HINT_T1 HEDLEY_STATIC_CAST(enum _mm_hint, 2) + #define SIMDE_MM_HINT_T2 HEDLEY_STATIC_CAST(enum _mm_hint, 3) + #define SIMDE_MM_HINT_ENTA HEDLEY_STATIC_CAST(enum _mm_hint, 4) + #define SIMDE_MM_HINT_ET0 HEDLEY_STATIC_CAST(enum _mm_hint, 5) + #define SIMDE_MM_HINT_ET1 HEDLEY_STATIC_CAST(enum _mm_hint, 6) + #define SIMDE_MM_HINT_ET2 HEDLEY_STATIC_CAST(enum _mm_hint, 7) +#else + #define SIMDE_MM_HINT_NTA 0 + #define SIMDE_MM_HINT_T0 1 + #define SIMDE_MM_HINT_T1 2 + #define SIMDE_MM_HINT_T2 3 + #define SIMDE_MM_HINT_ENTA 4 + #define SIMDE_MM_HINT_ET0 5 + #define SIMDE_MM_HINT_ET1 6 + #define SIMDE_MM_HINT_ET2 7 +#endif + +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wreserved-id-macro") + _Pragma("clang diagnostic ignored \"-Wreserved-id-macro\"") + #endif + #undef _MM_HINT_NTA + #define _MM_HINT_NTA SIMDE_MM_HINT_NTA + #undef _MM_HINT_T0 + #define _MM_HINT_T0 SIMDE_MM_HINT_T0 + #undef _MM_HINT_T1 + #define _MM_HINT_T1 SIMDE_MM_HINT_T1 + #undef _MM_HINT_T2 + #define _MM_HINT_T2 SIMDE_MM_HINT_T2 + #undef _MM_HINT_ETNA + #define _MM_HINT_ETNA SIMDE_MM_HINT_ETNA + #undef _MM_HINT_ET0 + #define _MM_HINT_ET0 SIMDE_MM_HINT_ET0 + #undef _MM_HINT_ET1 + #define _MM_HINT_ET1 SIMDE_MM_HINT_ET1 + #undef _MM_HINT_ET1 + #define _MM_HINT_ET2 SIMDE_MM_HINT_ET2 + HEDLEY_DIAGNOSTIC_POP +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_prefetch (char const* p, int i) { + #if defined(HEDLEY_GCC_VERSION) + __builtin_prefetch(p); + #else + (void) p; + #endif + + (void) i; +} +#if defined(SIMDE_X86_SSE_NATIVE) + #if defined(__clang__) && !SIMDE_DETECT_CLANG_VERSION_CHECK(10,0,0) /* https://reviews.llvm.org/D71718 */ + #define simde_mm_prefetch(p, i) \ + (__extension__({ \ + HEDLEY_DIAGNOSTIC_PUSH \ + HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + _mm_prefetch((p), (i)); \ + HEDLEY_DIAGNOSTIC_POP \ + })) + #else + #define simde_mm_prefetch(p, i) _mm_prefetch(p, i) + #endif +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) + #define _mm_prefetch(p, i) simde_mm_prefetch(p, i) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_negate_ps(simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return simde_mm_xor_ps(a, _mm_set1_ps(SIMDE_FLOAT32_C(-0.0))); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(8,1,0)) + r_.altivec_f32 = vec_neg(a_.altivec_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vnegq_f32(a_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_neg(a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + r_.altivec_f32 = vec_neg(a_.altivec_f32); + #elif defined(SIMDE_VECTOR_NEGATE) + r_.f32 = -a_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = -a_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_rcp_ps (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_rcp_ps(a); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4_t recip = vrecpeq_f32(a_.neon_f32); + + #if SIMDE_ACCURACY_PREFERENCE > 0 + for (int i = 0; i < SIMDE_ACCURACY_PREFERENCE ; ++i) { + recip = vmulq_f32(recip, vrecpsq_f32(recip, a_.neon_f32)); + } + #endif + + r_.neon_f32 = recip; + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_div(simde_mm_set1_ps(1.0f), a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_re(a_.altivec_f32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.f32 = 1.0f / a_.f32; + #elif defined(SIMDE_IEEE754_STORAGE) + /* https://stackoverflow.com/questions/12227126/division-as-multiply-and-lut-fast-float-division-reciprocal/12228234#12228234 */ + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + int32_t ix; + simde_float32 fx = a_.f32[i]; + simde_memcpy(&ix, &fx, sizeof(ix)); + int32_t x = INT32_C(0x7EF311C3) - ix; + simde_float32 temp; + simde_memcpy(&temp, &x, sizeof(temp)); + r_.f32[i] = temp * (SIMDE_FLOAT32_C(2.0) - temp * fx); + } + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = 1.0f / a_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_rcp_ps(a) simde_mm_rcp_ps((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_rcp_ss (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_rcp_ss(a); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_rcp_ps(a)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + r_.f32[0] = 1.0f / a_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_rcp_ss(a) simde_mm_rcp_ss((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_rsqrt_ps (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_rsqrt_ps(a); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vrsqrteq_f32(a_.neon_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_rsqrte(a_.altivec_f32); + #elif defined(SIMDE_IEEE754_STORAGE) + /* https://basesandframes.files.wordpress.com/2020/04/even_faster_math_functions_green_2020.pdf + Pages 100 - 103 */ + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + #if SIMDE_ACCURACY_PREFERENCE <= 0 + r_.i32[i] = INT32_C(0x5F37624F) - (a_.i32[i] >> 1); + #else + simde_float32 x = a_.f32[i]; + simde_float32 xhalf = SIMDE_FLOAT32_C(0.5) * x; + int32_t ix; + + simde_memcpy(&ix, &x, sizeof(ix)); + + #if SIMDE_ACCURACY_PREFERENCE == 1 + ix = INT32_C(0x5F375A82) - (ix >> 1); + #else + ix = INT32_C(0x5F37599E) - (ix >> 1); + #endif + + simde_memcpy(&x, &ix, sizeof(x)); + + #if SIMDE_ACCURACY_PREFERENCE >= 2 + x = x * (SIMDE_FLOAT32_C(1.5008909) - xhalf * x * x); + #endif + x = x * (SIMDE_FLOAT32_C(1.5008909) - xhalf * x * x); + + r_.f32[i] = x; + #endif + } + #elif defined(simde_math_sqrtf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = 1.0f / simde_math_sqrtf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_rsqrt_ps(a) simde_mm_rsqrt_ps((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_rsqrt_ss (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_rsqrt_ss(a); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_rsqrt_ps(a)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsetq_lane_f32(vgetq_lane_f32(simde_mm_rsqrt_ps(a).neon_f32, 0), a_.neon_f32, 0); + #elif defined(SIMDE_IEEE754_STORAGE) + { + #if SIMDE_ACCURACY_PREFERENCE <= 0 + r_.i32[0] = INT32_C(0x5F37624F) - (a_.i32[0] >> 1); + #else + simde_float32 x = a_.f32[0]; + simde_float32 xhalf = SIMDE_FLOAT32_C(0.5) * x; + int32_t ix; + + simde_memcpy(&ix, &x, sizeof(ix)); + + #if SIMDE_ACCURACY_PREFERENCE == 1 + ix = INT32_C(0x5F375A82) - (ix >> 1); + #else + ix = INT32_C(0x5F37599E) - (ix >> 1); + #endif + + simde_memcpy(&x, &ix, sizeof(x)); + + #if SIMDE_ACCURACY_PREFERENCE >= 2 + x = x * (SIMDE_FLOAT32_C(1.5008909) - xhalf * x * x); + #endif + x = x * (SIMDE_FLOAT32_C(1.5008909) - xhalf * x * x); + + r_.f32[0] = x; + #endif + } + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #elif defined(simde_math_sqrtf) + r_.f32[0] = 1.0f / simde_math_sqrtf(a_.f32[0]); + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_rsqrt_ss(a) simde_mm_rsqrt_ss((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sad_pu8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_sad_pu8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint16x4_t t = vpaddl_u8(vabd_u8(a_.neon_u8, b_.neon_u8)); + uint16_t r0 = t[0] + t[1] + t[2] + t[3]; + r_.neon_u16 = vset_lane_u16(r0, vdup_n_u16(0), 0); + #else + uint16_t sum = 0; + + #if defined(SIMDE_HAVE_STDLIB_H) + SIMDE_VECTORIZE_REDUCTION(+:sum) + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + sum += HEDLEY_STATIC_CAST(uint8_t, abs(a_.u8[i] - b_.u8[i])); + } + + r_.i16[0] = HEDLEY_STATIC_CAST(int16_t, sum); + r_.i16[1] = 0; + r_.i16[2] = 0; + r_.i16[3] = 0; + #else + HEDLEY_UNREACHABLE(); + #endif + #endif + + return simde__m64_from_private(r_); + #endif +} +#define simde_m_psadbw(a, b) simde_mm_sad_pu8(a, b) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_sad_pu8(a, b) simde_mm_sad_pu8(a, b) +# define _m_psadbw(a, b) simde_mm_sad_pu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_set_ss (simde_float32 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_set_ss(a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vsetq_lane_f32(a, vdupq_n_f32(SIMDE_FLOAT32_C(0.0)), 0); + #else + return simde_mm_set_ps(SIMDE_FLOAT32_C(0.0), SIMDE_FLOAT32_C(0.0), SIMDE_FLOAT32_C(0.0), a); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_set_ss(a) simde_mm_set_ss(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_setr_ps (simde_float32 e3, simde_float32 e2, simde_float32 e1, simde_float32 e0) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_setr_ps(e3, e2, e1, e0); + #else + return simde_mm_set_ps(e0, e1, e2, e3); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_setr_ps(e3, e2, e1, e0) simde_mm_setr_ps(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_setzero_ps (void) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_setzero_ps(); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vdupq_n_f32(SIMDE_FLOAT32_C(0.0)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + return vec_splats(SIMDE_FLOAT32_C(0.0)); + #else + simde__m128 r; + simde_memset(&r, 0, sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_setzero_ps() simde_mm_setzero_ps() +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_undefined_ps (void) { + simde__m128_private r_; + + #if defined(SIMDE_HAVE_UNDEFINED128) + r_.n = _mm_undefined_ps(); + #elif !defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + r_ = simde__m128_to_private(simde_mm_setzero_ps()); + #endif + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_undefined_ps() simde_mm_undefined_ps() +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) +HEDLEY_DIAGNOSTIC_POP +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_setone_ps (void) { + simde__m128 t = simde_mm_setzero_ps(); + return simde_mm_cmpeq_ps(t, t); +} + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_sfence (void) { + /* TODO: Use Hedley. */ + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_sfence(); + #elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) + __atomic_thread_fence(__ATOMIC_SEQ_CST); + #elif !defined(__INTEL_COMPILER) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) + #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 9) + __atomic_thread_fence(__ATOMIC_SEQ_CST); + #else + atomic_thread_fence(memory_order_seq_cst); + #endif + #elif defined(_MSC_VER) + MemoryBarrier(); + #elif HEDLEY_HAS_EXTENSION(c_atomic) + __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); + #elif defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) + __sync_synchronize(); + #elif defined(_OPENMP) + #pragma omp critical(simde_mm_sfence_) + { } + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_sfence() simde_mm_sfence() +#endif + +#define SIMDE_MM_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w)) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _MM_SHUFFLE(z, y, x, w) SIMDE_MM_SHUFFLE(z, y, x, w) +#endif + +#if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) +# define simde_mm_shuffle_pi16(a, imm8) _mm_shuffle_pi16(a, imm8) +#elif defined(SIMDE_SHUFFLE_VECTOR_) +# define simde_mm_shuffle_pi16(a, imm8) (__extension__ ({ \ + const simde__m64_private simde__tmp_a_ = simde__m64_to_private(a); \ + simde__m64_from_private((simde__m64_private) { .i16 = \ + SIMDE_SHUFFLE_VECTOR_(16, 8, \ + (simde__tmp_a_).i16, \ + (simde__tmp_a_).i16, \ + (((imm8) ) & 3), \ + (((imm8) >> 2) & 3), \ + (((imm8) >> 4) & 3), \ + (((imm8) >> 6) & 3)) }); })) +#else +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_shuffle_pi16 (simde__m64 a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m64_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + for (size_t i = 0 ; i < sizeof(r_.i16) / sizeof(r_.i16[0]) ; i++) { + r_.i16[i] = a_.i16[(imm8 >> (i * 2)) & 3]; + } + +HEDLEY_DIAGNOSTIC_PUSH +#if HEDLEY_HAS_WARNING("-Wconditional-uninitialized") +# pragma clang diagnostic ignored "-Wconditional-uninitialized" +#endif + return simde__m64_from_private(r_); +HEDLEY_DIAGNOSTIC_POP +} +#endif +#if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) +# define simde_m_pshufw(a, imm8) _m_pshufw(a, imm8) +#else +# define simde_m_pshufw(a, imm8) simde_mm_shuffle_pi16(a, imm8) +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_shuffle_pi16(a, imm8) simde_mm_shuffle_pi16(a, imm8) +# define _m_pshufw(a, imm8) simde_mm_shuffle_pi16(a, imm8) +#endif + +#if defined(SIMDE_X86_SSE_NATIVE) && !defined(__PGI) +# define simde_mm_shuffle_ps(a, b, imm8) _mm_shuffle_ps(a, b, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_shuffle_ps(a, b, imm8) \ + __extension__({ \ + float32x4_t ret; \ + ret = vmovq_n_f32( \ + vgetq_lane_f32(a, (imm8) & (0x3))); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(a, ((imm8) >> 2) & 0x3), \ + ret, 1); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(b, ((imm8) >> 4) & 0x3), \ + ret, 2); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(b, ((imm8) >> 6) & 0x3), \ + ret, 3); \ + }) +#elif defined(SIMDE_SHUFFLE_VECTOR_) +# define simde_mm_shuffle_ps(a, b, imm8) (__extension__ ({ \ + simde__m128_from_private((simde__m128_private) { .f32 = \ + SIMDE_SHUFFLE_VECTOR_(32, 16, \ + simde__m128_to_private(a).f32, \ + simde__m128_to_private(b).f32, \ + (((imm8) ) & 3), \ + (((imm8) >> 2) & 3), \ + (((imm8) >> 4) & 3) + 4, \ + (((imm8) >> 6) & 3) + 4) }); })) +#else +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_shuffle_ps (simde__m128 a, simde__m128 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.f32[0] = a_.f32[(imm8 >> 0) & 3]; + r_.f32[1] = a_.f32[(imm8 >> 2) & 3]; + r_.f32[2] = b_.f32[(imm8 >> 4) & 3]; + r_.f32[3] = b_.f32[(imm8 >> 6) & 3]; + + return simde__m128_from_private(r_); +} +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_shuffle_ps(a, b, imm8) simde_mm_shuffle_ps((a), (b), imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_sqrt_ps (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_sqrt_ps(a); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vsqrtq_f32(a_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4_t est = vrsqrteq_f32(a_.neon_f32); + for (int i = 0 ; i <= SIMDE_ACCURACY_PREFERENCE ; i++) { + est = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a_.neon_f32, est), est), est); + } + r_.neon_f32 = vmulq_f32(a_.neon_f32, est); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_sqrt(a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_14_NATIVE) + r_.altivec_f32 = vec_sqrt(a_.altivec_f32); + #elif defined(simde_math_sqrt) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < sizeof(r_.f32) / sizeof(r_.f32[0]) ; i++) { + r_.f32[i] = simde_math_sqrtf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_sqrt_ps(a) simde_mm_sqrt_ps((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_sqrt_ss (simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_sqrt_ss(a); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_sqrt_ps(a)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32_t value = + vgetq_lane_f32(simde__m128_to_private(simde_mm_sqrt_ps(a)).neon_f32, 0); + r_.neon_f32 = vsetq_lane_f32(value, a_.neon_f32, 0); + #elif defined(simde_math_sqrtf) + r_.f32[0] = simde_math_sqrtf(a_.f32[0]); + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_sqrt_ss(a) simde_mm_sqrt_ss((a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store_ps (simde_float32 mem_addr[4], simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_store_ps(mem_addr, a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_f32(mem_addr, a_.neon_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + vec_st(a_.altivec_f32, 0, mem_addr); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + wasm_v128_store(mem_addr, a_.wasm_v128); + #else + simde_memcpy(mem_addr, &a_, sizeof(a)); + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_store_ps(mem_addr, a) simde_mm_store_ps(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store1_ps (simde_float32 mem_addr[4], simde__m128 a) { + simde_float32* mem_addr_ = SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m128); + + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_store_ps1(mem_addr_, a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_f32(mem_addr_, vdupq_lane_f32(vget_low_f32(a_.neon_f32), 0)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + wasm_v128_store(mem_addr_, wasm_v32x4_shuffle(a_.wasm_v128, a_.wasm_v128, 0, 0, 0, 0)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + vec_st(vec_splat(a_.altivec_f32, 0), 0, mem_addr_); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + simde__m128_private tmp_; + tmp_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, a_.f32, 0, 0, 0, 0); + simde_mm_store_ps(mem_addr_, tmp_.f32); + #else + SIMDE_VECTORIZE_ALIGNED(mem_addr_:16) + for (size_t i = 0 ; i < sizeof(a_.f32) / sizeof(a_.f32[0]) ; i++) { + mem_addr_[i] = a_.f32[0]; + } + #endif + #endif +} +#define simde_mm_store_ps1(mem_addr, a) simde_mm_store1_ps(mem_addr, a) +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_store_ps1(mem_addr, a) simde_mm_store1_ps(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +# define _mm_store1_ps(mem_addr, a) simde_mm_store1_ps(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store_ss (simde_float32* mem_addr, simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_store_ss(mem_addr, a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_lane_f32(mem_addr, a_.neon_f32, 0); + #else + *mem_addr = a_.f32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_store_ss(mem_addr, a) simde_mm_store_ss(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeh_pi (simde__m64* mem_addr, simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_storeh_pi(HEDLEY_REINTERPRET_CAST(__m64*, mem_addr), a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1_f32(HEDLEY_REINTERPRET_CAST(float32_t*, mem_addr), vget_high_f32(a_.neon_f32)); + #else + simde_memcpy(mem_addr, &(a_.m64[1]), sizeof(a_.m64[1])); + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_storeh_pi(mem_addr, a) simde_mm_storeh_pi(mem_addr, (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storel_pi (simde__m64* mem_addr, simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_storel_pi(HEDLEY_REINTERPRET_CAST(__m64*, mem_addr), a); + #else + simde__m64_private* dest_ = HEDLEY_REINTERPRET_CAST(simde__m64_private*, mem_addr); + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + dest_->neon_f32 = vget_low_f32(a_.neon_f32); + #else + dest_->f32[0] = a_.f32[0]; + dest_->f32[1] = a_.f32[1]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_storel_pi(mem_addr, a) simde_mm_storel_pi(mem_addr, (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storer_ps (simde_float32 mem_addr[4], simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_storer_ps(mem_addr, a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + vec_st(vec_reve(a_.altivec_f32), 0, mem_addr); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4_t tmp = vrev64q_f32(a_.neon_f32); + vst1q_f32(mem_addr, vextq_f32(tmp, tmp, 2)); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + a_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, a_.f32, 3, 2, 1, 0); + simde_mm_store_ps(mem_addr, simde__m128_from_private(a_)); + #else + SIMDE_VECTORIZE_ALIGNED(mem_addr:16) + for (size_t i = 0 ; i < sizeof(a_.f32) / sizeof(a_.f32[0]) ; i++) { + mem_addr[i] = a_.f32[((sizeof(a_.f32) / sizeof(a_.f32[0])) - 1) - i]; + } + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_storer_ps(mem_addr, a) simde_mm_storer_ps(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeu_ps (simde_float32 mem_addr[4], simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_storeu_ps(mem_addr, a); + #else + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_f32(mem_addr, a_.neon_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + vec_vsx_st(a_.altivec_f32, 0, mem_addr); + #else + simde_memcpy(mem_addr, &a_, sizeof(a_)); + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_storeu_ps(mem_addr, a) simde_mm_storeu_ps(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_sub_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_sub_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vsubq_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_sub(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_sub(a_.altivec_f32, b_.altivec_f32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 - b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] - b_.f32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_sub_ps(a, b) simde_mm_sub_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_sub_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_sub_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_sub_ps(a, b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + r_.f32[0] = a_.f32[0] - b_.f32[0]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[3]; + + return simde__m128_from_private(r_); + #endif +} + +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_sub_ss(a, b) simde_mm_sub_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomieq_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_ucomieq_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_eq_b = vceqq_f32(a_.neon_f32, b_.neon_f32); + r = !!(vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_eq_b), 0) != 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f32[0] == b_.f32[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f32[0] == b_.f32[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_ucomieq_ss(a, b) simde_mm_ucomieq_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomige_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_ucomige_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_ge_b = vcgeq_f32(a_.neon_f32, b_.neon_f32); + r = !!(vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_ge_b), 0) != 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f32[0] >= b_.f32[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f32[0] >= b_.f32[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_ucomige_ss(a, b) simde_mm_ucomige_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomigt_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_ucomigt_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_gt_b = vcgtq_f32(a_.neon_f32, b_.neon_f32); + r = !!(vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_gt_b), 0) != 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f32[0] > b_.f32[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f32[0] > b_.f32[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_ucomigt_ss(a, b) simde_mm_ucomigt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomile_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_ucomile_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_le_b = vcleq_f32(a_.neon_f32, b_.neon_f32); + r = !!(vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_le_b), 0) != 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f32[0] <= b_.f32[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f32[0] <= b_.f32[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_ucomile_ss(a, b) simde_mm_ucomile_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomilt_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_ucomilt_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_lt_b = vcltq_f32(a_.neon_f32, b_.neon_f32); + r = !!(vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_lt_b), 0) != 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f32[0] < b_.f32[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f32[0] < b_.f32[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_ucomilt_ss(a, b) simde_mm_ucomilt_ss((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomineq_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_ucomineq_ss(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t a_not_nan = vceqq_f32(a_.neon_f32, a_.neon_f32); + uint32x4_t b_not_nan = vceqq_f32(b_.neon_f32, b_.neon_f32); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_neq_b = vmvnq_u32(vceqq_f32(a_.neon_f32, b_.neon_f32)); + r = !!(vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_neq_b), 0) != 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f32[0] != b_.f32[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f32[0] != b_.f32[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_ucomineq_ss(a, b) simde_mm_ucomineq_ss((a), (b)) +#endif + +#if defined(SIMDE_X86_SSE_NATIVE) +# if defined(__has_builtin) +# if __has_builtin(__builtin_ia32_undef128) +# define SIMDE_HAVE_UNDEFINED128 +# endif +# elif !defined(__PGI) && !defined(SIMDE_BUG_GCC_REV_208793) && !defined(_MSC_VER) +# define SIMDE_HAVE_UNDEFINED128 +# endif +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_unpackhi_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_unpackhi_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vzip2q_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x2_t a1 = vget_high_f32(a_.neon_f32); + float32x2_t b1 = vget_high_f32(b_.neon_f32); + float32x2x2_t result = vzip_f32(a1, b1); + r_.neon_f32 = vcombine_f32(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 2, 6, 3, 7); + #else + r_.f32[0] = a_.f32[2]; + r_.f32[1] = b_.f32[2]; + r_.f32[2] = a_.f32[3]; + r_.f32[3] = b_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_unpackhi_ps(a, b) simde_mm_unpackhi_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_unpacklo_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE_NATIVE) + return _mm_unpacklo_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vzip1q_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_f32 = vec_mergeh(a_.altivec_f32, b_.altivec_f32); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 0, 4, 1, 5); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x2_t a1 = vget_low_f32(a_.neon_f32); + float32x2_t b1 = vget_low_f32(b_.neon_f32); + float32x2x2_t result = vzip_f32(a1, b1); + r_.neon_f32 = vcombine_f32(result.val[0], result.val[1]); + #else + r_.f32[0] = a_.f32[0]; + r_.f32[1] = b_.f32[0]; + r_.f32[2] = a_.f32[1]; + r_.f32[3] = b_.f32[1]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_unpacklo_ps(a, b) simde_mm_unpacklo_ps((a), (b)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_stream_pi (simde__m64* mem_addr, simde__m64 a) { + #if defined(SIMDE_X86_SSE_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + _mm_stream_pi(HEDLEY_REINTERPRET_CAST(__m64*, mem_addr), a); + #else + simde__m64_private* + dest = HEDLEY_REINTERPRET_CAST(simde__m64_private*, mem_addr), + a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + dest->i64[0] = vget_lane_s64(a_.neon_i64, 0); + #else + dest->i64[0] = a_.i64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_stream_pi(mem_addr, a) simde_mm_stream_pi(mem_addr, (a)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_stream_ps (simde_float32 mem_addr[4], simde__m128 a) { + #if defined(SIMDE_X86_SSE_NATIVE) + _mm_stream_ps(mem_addr, a); + #elif HEDLEY_HAS_BUILTIN(__builtin_nontemporal_store) && defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + simde__m128_private a_ = simde__m128_to_private(a); + __builtin_nontemporal_store(a_.f32, SIMDE_ALIGN_CAST(__typeof__(a_.f32)*, mem_addr)); + #else + simde_mm_store_ps(mem_addr, a); + #endif +} +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _mm_stream_ps(mem_addr, a) simde_mm_stream_ps(SIMDE_CHECKED_REINTERPRET_CAST(float*, simde_float32*, mem_addr), (a)) +#endif + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) +#define SIMDE_MM_TRANSPOSE4_PS(row0, row1, row2, row3) \ + do { \ + float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \ + float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \ + row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \ + vget_low_f32(ROW23.val[0])); \ + row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \ + vget_low_f32(ROW23.val[1])); \ + row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \ + vget_high_f32(ROW23.val[0])); \ + row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \ + vget_high_f32(ROW23.val[1])); \ + } while (0) +#else +#define SIMDE_MM_TRANSPOSE4_PS(row0, row1, row2, row3) \ + do { \ + simde__m128 tmp3, tmp2, tmp1, tmp0; \ + tmp0 = simde_mm_unpacklo_ps((row0), (row1)); \ + tmp2 = simde_mm_unpacklo_ps((row2), (row3)); \ + tmp1 = simde_mm_unpackhi_ps((row0), (row1)); \ + tmp3 = simde_mm_unpackhi_ps((row2), (row3)); \ + row0 = simde_mm_movelh_ps(tmp0, tmp2); \ + row1 = simde_mm_movehl_ps(tmp2, tmp0); \ + row2 = simde_mm_movelh_ps(tmp1, tmp3); \ + row3 = simde_mm_movehl_ps(tmp3, tmp1); \ + } while (0) +#endif +#if defined(SIMDE_X86_SSE_ENABLE_NATIVE_ALIASES) +# define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) SIMDE_MM_TRANSPOSE4_PS(row0, row1, row2, row3) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_SSE_H) */ +/* :: End ../simde/simde/x86/sse.h :: */ +#if !defined(SIMDE_X86_AVX_H) +#define SIMDE_X86_AVX_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/sse4.2.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017 Evan Nemerson + * 2020 Hidayat Khan + */ + +#if !defined(SIMDE_X86_SSE4_2_H) +#define SIMDE_X86_SSE4_2_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/sse4.1.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +#if !defined(SIMDE_X86_SSE4_1_H) +#define SIMDE_X86_SSE4_1_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/ssse3.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +#if !defined(SIMDE_X86_SSSE3_H) +#define SIMDE_X86_SSSE3_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/sse3.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + */ + +#if !defined(SIMDE_X86_SSE3_H) +#define SIMDE_X86_SSE3_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ +/* :: Begin ../simde/simde/x86/sse2.h :: */ +/* SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Copyright: + * 2017-2020 Evan Nemerson + * 2015-2017 John W. Ratcliff + * 2015 Brandon Rowlett + * 2015 Ken Fast + * 2017 Hasindu Gamaarachchi + * 2018 Jeff Daily + */ + +#if !defined(SIMDE_X86_SSE2_H) +#define SIMDE_X86_SSE2_H + +/* AUTOMATICALLY GENERATED FILE, DO NOT MODIFY */ +/* e8b7a2ec175ceb3725ce0827ef9a6725b6309cc9 */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_16 int8_t i8 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int16_t i16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int32_t i32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int64_t i64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint8_t u8 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint16_t u16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint32_t u32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint64_t u64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_16 simde_int128 i128 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 simde_uint128 u128 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #endif + SIMDE_ALIGN_TO_16 simde_float32 f32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 simde_float64 f64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + + SIMDE_ALIGN_TO_16 int_fast32_t i32f SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint_fast32_t u32f SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_16 int8_t i8[16]; + SIMDE_ALIGN_TO_16 int16_t i16[8]; + SIMDE_ALIGN_TO_16 int32_t i32[4]; + SIMDE_ALIGN_TO_16 int64_t i64[2]; + SIMDE_ALIGN_TO_16 uint8_t u8[16]; + SIMDE_ALIGN_TO_16 uint16_t u16[8]; + SIMDE_ALIGN_TO_16 uint32_t u32[4]; + SIMDE_ALIGN_TO_16 uint64_t u64[2]; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_16 simde_int128 i128[1]; + SIMDE_ALIGN_TO_16 simde_uint128 u128[1]; + #endif + SIMDE_ALIGN_TO_16 simde_float32 f32[4]; + SIMDE_ALIGN_TO_16 simde_float64 f64[2]; + + SIMDE_ALIGN_TO_16 int_fast32_t i32f[16 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_16 uint_fast32_t u32f[16 / sizeof(uint_fast32_t)]; + #endif + + SIMDE_ALIGN_TO_16 simde__m64_private m64_private[2]; + SIMDE_ALIGN_TO_16 simde__m64 m64[2]; + + #if defined(SIMDE_X86_SSE2_NATIVE) + SIMDE_ALIGN_TO_16 __m128i n; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_TO_16 int8x16_t neon_i8; + SIMDE_ALIGN_TO_16 int16x8_t neon_i16; + SIMDE_ALIGN_TO_16 int32x4_t neon_i32; + SIMDE_ALIGN_TO_16 int64x2_t neon_i64; + SIMDE_ALIGN_TO_16 uint8x16_t neon_u8; + SIMDE_ALIGN_TO_16 uint16x8_t neon_u16; + SIMDE_ALIGN_TO_16 uint32x4_t neon_u32; + SIMDE_ALIGN_TO_16 uint64x2_t neon_u64; + #if defined(__ARM_FP16_FORMAT_IEEE) + SIMDE_ALIGN_TO_16 float16x8_t neon_f16; + #endif + SIMDE_ALIGN_TO_16 float32x4_t neon_f32; + #if defined(SIMDE_ARCH_AARCH64) + SIMDE_ALIGN_TO_16 float64x2_t neon_f64; + #endif + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + SIMDE_ALIGN_TO_16 v128_t wasm_v128; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed char) altivec_i8; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed short) altivec_i16; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32; + #if defined(__UINT_FAST32_TYPE__) && (defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE)) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(__INT_FAST32_TYPE__) altivec_i32f; + #else + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32f; + #endif + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) altivec_u8; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) altivec_u16; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32; + #if defined(__UINT_FAST32_TYPE__) && (defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE)) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(__UINT_FAST32_TYPE__) altivec_u32f; + #else + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32f; + #endif + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(float) altivec_f32; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed long long) altivec_i64; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) altivec_u64; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(double) altivec_f64; + #endif + #endif +} simde__m128i_private; + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_16 int8_t i8 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int16_t i16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int32_t i32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int64_t i64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint8_t u8 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint16_t u16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint32_t u32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint64_t u64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 simde_float32 f32 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 simde_float64 f64 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 int_fast32_t i32f SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_16 uint_fast32_t u32f SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_16 int8_t i8[16]; + SIMDE_ALIGN_TO_16 int16_t i16[8]; + SIMDE_ALIGN_TO_16 int32_t i32[4]; + SIMDE_ALIGN_TO_16 int64_t i64[2]; + SIMDE_ALIGN_TO_16 uint8_t u8[16]; + SIMDE_ALIGN_TO_16 uint16_t u16[8]; + SIMDE_ALIGN_TO_16 uint32_t u32[4]; + SIMDE_ALIGN_TO_16 uint64_t u64[2]; + SIMDE_ALIGN_TO_16 simde_float32 f32[4]; + SIMDE_ALIGN_TO_16 simde_float64 f64[2]; + SIMDE_ALIGN_TO_16 int_fast32_t i32f[16 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_16 uint_fast32_t u32f[16 / sizeof(uint_fast32_t)]; + #endif + + SIMDE_ALIGN_TO_16 simde__m64_private m64_private[2]; + SIMDE_ALIGN_TO_16 simde__m64 m64[2]; + + #if defined(SIMDE_X86_SSE2_NATIVE) + SIMDE_ALIGN_TO_16 __m128d n; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_TO_16 int8x16_t neon_i8; + SIMDE_ALIGN_TO_16 int16x8_t neon_i16; + SIMDE_ALIGN_TO_16 int32x4_t neon_i32; + SIMDE_ALIGN_TO_16 int64x2_t neon_i64; + SIMDE_ALIGN_TO_16 uint8x16_t neon_u8; + SIMDE_ALIGN_TO_16 uint16x8_t neon_u16; + SIMDE_ALIGN_TO_16 uint32x4_t neon_u32; + SIMDE_ALIGN_TO_16 uint64x2_t neon_u64; + SIMDE_ALIGN_TO_16 float32x4_t neon_f32; + #if defined(SIMDE_ARCH_AARCH64) + SIMDE_ALIGN_TO_16 float64x2_t neon_f64; + #endif + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + SIMDE_ALIGN_TO_16 v128_t wasm_v128; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed char) altivec_i8; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed short) altivec_i16; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32; + #if defined(__INT_FAST32_TYPE__) && (defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE)) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(__INT_FAST32_TYPE__) altivec_i32f; + #else + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32f; + #endif + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) altivec_u8; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) altivec_u16; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32; + #if defined(__UINT_FAST32_TYPE__) && (defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE)) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(__UINT_FAST32_TYPE__) altivec_u32f; + #else + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32f; + #endif + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(float) altivec_f32; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed long long) altivec_i64; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) altivec_u64; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(double) altivec_f64; + #endif + #endif +} simde__m128d_private; + +#if defined(SIMDE_X86_SSE2_NATIVE) + typedef __m128i simde__m128i; + typedef __m128d simde__m128d; +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + typedef int64x2_t simde__m128i; +# if defined(SIMDE_ARCH_AARCH64) + typedef float64x2_t simde__m128d; +# elif defined(SIMDE_VECTOR_SUBSCRIPT) + typedef simde_float64 simde__m128d SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; +# else + typedef simde__m128d_private simde__m128d; +# endif +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + typedef v128_t simde__m128i; + typedef v128_t simde__m128d; +#elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + typedef SIMDE_POWER_ALTIVEC_VECTOR(float) simde__m128i; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + typedef SIMDE_POWER_ALTIVEC_VECTOR(double) simde__m128d; + #else + typedef simde__m128d_private simde__m128d; + #endif +#elif defined(SIMDE_VECTOR_SUBSCRIPT) + typedef int64_t simde__m128i SIMDE_ALIGN_TO_16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; + typedef simde_float64 simde__m128d SIMDE_ALIGN_TO_16 SIMDE_VECTOR(16) SIMDE_MAY_ALIAS; +#else + typedef simde__m128i_private simde__m128i; + typedef simde__m128d_private simde__m128d; +#endif + +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + typedef simde__m128i __m128i; + typedef simde__m128d __m128d; +#endif + +HEDLEY_STATIC_ASSERT(16 == sizeof(simde__m128i), "simde__m128i size incorrect"); +HEDLEY_STATIC_ASSERT(16 == sizeof(simde__m128i_private), "simde__m128i_private size incorrect"); +HEDLEY_STATIC_ASSERT(16 == sizeof(simde__m128d), "simde__m128d size incorrect"); +HEDLEY_STATIC_ASSERT(16 == sizeof(simde__m128d_private), "simde__m128d_private size incorrect"); +#if defined(SIMDE_CHECK_ALIGNMENT) && defined(SIMDE_ALIGN_OF) +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m128i) == 16, "simde__m128i is not 16-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m128i_private) == 16, "simde__m128i_private is not 16-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m128d) == 16, "simde__m128d is not 16-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m128d_private) == 16, "simde__m128d_private is not 16-byte aligned"); +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde__m128i_from_private(simde__m128i_private v) { + simde__m128i r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i_private +simde__m128i_to_private(simde__m128i v) { + simde__m128i_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde__m128d_from_private(simde__m128d_private v) { + simde__m128d r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d_private +simde__m128d_to_private(simde__m128d v) { + simde__m128d_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, int8x16_t, neon, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, int16x8_t, neon, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, int32x4_t, neon, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, int64x2_t, neon, i64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, uint8x16_t, neon, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, uint16x8_t, neon, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, uint32x4_t, neon, u32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, uint64x2_t, neon, u64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, float32x4_t, neon, f32) + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, float64x2_t, neon, f64) + #endif +#elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(signed char), altivec, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(signed short), altivec, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(signed int), altivec, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(unsigned char), altivec, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(unsigned short), altivec, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(unsigned int), altivec, u32) + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), altivec, u64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, SIMDE_POWER_ALTIVEC_VECTOR(signed long long), altivec, i64) + #endif +#endif /* defined(SIMDE_ARM_NEON_A32V7_NATIVE) */ + +#if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, int8x16_t, neon, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, int16x8_t, neon, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, int32x4_t, neon, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, int64x2_t, neon, i64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, uint8x16_t, neon, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, uint16x8_t, neon, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, uint32x4_t, neon, u32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, uint64x2_t, neon, u64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, float32x4_t, neon, f32) + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, float64x2_t, neon, f64) + #endif +#elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(signed char), altivec, i8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(signed short), altivec, i16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(signed int), altivec, i32) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(unsigned char), altivec, u8) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(unsigned short), altivec, u16) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(unsigned int), altivec, u32) + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), altivec, u64) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(signed long long), altivec, i64) + #if defined(SIMDE_BUG_GCC_95782) + SIMDE_FUNCTION_ATTRIBUTES + SIMDE_POWER_ALTIVEC_VECTOR(double) + simde__m128d_to_altivec_f64(simde__m128d value) { + simde__m128d_private r_ = simde__m128d_to_private(value); + return r_.altivec_f64; + } + + SIMDE_FUNCTION_ATTRIBUTES + simde__m128d + simde__m128d_from_altivec_f64(SIMDE_POWER_ALTIVEC_VECTOR(double) value) { + simde__m128d_private r_; + r_.altivec_f64 = value; + return simde__m128d_from_private(r_); + } + #else + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, SIMDE_POWER_ALTIVEC_VECTOR(double), altivec, f64) + #endif + #endif +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128d, v128_t, wasm, v128); + SIMDE_X86_GENERATE_CONVERSION_FUNCTION(m128i, v128_t, wasm, v128); +#endif /* defined(SIMDE_ARM_NEON_A32V7_NATIVE) */ + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_set_pd (simde_float64 e1, simde_float64 e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_pd(e1, e0); + #else + simde__m128d_private r_; + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_make(e0, e1); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + SIMDE_ALIGN_TO_16 simde_float64 data[2] = { e0, e1 }; + r_.neon_f64 = vld1q_f64(data); + #else + r_.f64[0] = e0; + r_.f64[1] = e1; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_pd(e1, e0) simde_mm_set_pd(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_set1_pd (simde_float64 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set1_pd(a); + #else + simde__m128d_private r_; + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_splat(a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vdupq_n_f64(a); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = vec_splats(HEDLEY_STATIC_CAST(double, a)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.f64[i] = a; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#define simde_mm_set_pd1(a) simde_mm_set1_pd(a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set1_pd(a) simde_mm_set1_pd(a) + #define _mm_set_pd1(a) simde_mm_set1_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_abs_pd(simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + simde_float64 mask_; + uint64_t u64_ = UINT64_C(0x7FFFFFFFFFFFFFFF); + simde_memcpy(&mask_, &u64_, sizeof(u64_)); + return _mm_and_pd(_mm_set1_pd(mask_), a); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V8_NATIVE) + r_.neon_f64 = vabsq_f64(a_.neon_f64); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = vec_abs(a_.altivec_f64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_fabs(a_.f64[i]); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_not_pd(simde__m128d a) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) + __m128i ai = _mm_castpd_si128(a); + return _mm_castsi128_pd(_mm_ternarylogic_epi64(ai, ai, ai, 0x55)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vmvnq_s32(a_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + r_.altivec_f64 = vec_nor(a_.altivec_f64, a_.altivec_f64); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_nor(a_.altivec_i32, a_.altivec_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_not(a_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~(a_.i32f[i]); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_select_pd(simde__m128d a, simde__m128d b, simde__m128d mask) { + /* This function is for when you want to blend two elements together + * according to a mask. It is similar to _mm_blendv_pd, except that + * it is undefined whether the blend is based on the highest bit in + * each lane (like blendv) or just bitwise operations. This allows + * us to implement the function efficiently everywhere. + * + * Basically, you promise that all the lanes in mask are either 0 or + * ~0. */ + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_blendv_pd(a, b, mask); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b), + mask_ = simde__m128d_to_private(mask); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 ^ ((a_.i64 ^ b_.i64) & mask_.i64); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vbslq_s64(mask_.neon_u64, b_.neon_i64, a_.neon_i64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] ^ ((a_.i64[i] ^ b_.i64[i]) & mask_.i64[i]); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_add_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_add_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vaddq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i8 = vec_add(a_.altivec_i8, b_.altivec_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = a_.i8 + b_.i8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] + b_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_epi8(a, b) simde_mm_add_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_add_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_add_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vaddq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i16 = vec_add(a_.altivec_i16, b_.altivec_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 + b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] + b_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_epi16(a, b) simde_mm_add_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_add_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_add_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vaddq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_add(a_.altivec_i32, b_.altivec_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 + b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] + b_.i32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_epi32(a, b) simde_mm_add_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_add_epi64 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_add_epi64(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vaddq_s64(a_.neon_i64, b_.neon_i64); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + r_.altivec_i64 = vec_add(a_.altivec_i64, b_.altivec_i64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i64x2_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 + b_.i64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] + b_.i64[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_epi64(a, b) simde_mm_add_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_add_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_add_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vaddq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + r_.altivec_f64 = vec_add(a_.altivec_f64, b_.altivec_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_add(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 + b_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] + b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_pd(a, b) simde_mm_add_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_move_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_move_sd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vsetq_lane_f64(vgetq_lane_f64(b_.neon_f64, 0), a_.neon_f64, 0); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + #if defined(HEDLEY_IBM_VERSION) + r_.altivec_f64 = vec_xxpermdi(a_.altivec_f64, b_.altivec_f64, 1); + #else + r_.altivec_f64 = vec_xxpermdi(b_.altivec_f64, a_.altivec_f64, 1); + #endif + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v64x2_shuffle(a_.wasm_v128, b_.wasm_v128, 2, 1); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, b_.f64, 2, 1); + #else + r_.f64[0] = b_.f64[0]; + r_.f64[1] = a_.f64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_move_sd(a, b) simde_mm_move_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_add_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_add_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_add_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.f64[0] = a_.f64[0] + b_.f64[0]; + r_.f64[1] = a_.f64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_sd(a, b) simde_mm_add_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_add_si64 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_add_si64(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vadd_s64(a_.neon_i64, b_.neon_i64); + #else + r_.i64[0] = a_.i64[0] + b_.i64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_add_si64(a, b) simde_mm_add_si64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_adds_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_adds_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vqaddq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_add_saturate(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i8 = vec_adds(a_.altivec_i8, b_.altivec_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + const int_fast16_t tmp = + HEDLEY_STATIC_CAST(int_fast16_t, a_.i8[i]) + + HEDLEY_STATIC_CAST(int_fast16_t, b_.i8[i]); + r_.i8[i] = HEDLEY_STATIC_CAST(int8_t, ((tmp < INT8_MAX) ? ((tmp > INT8_MIN) ? tmp : INT8_MIN) : INT8_MAX)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_adds_epi8(a, b) simde_mm_adds_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_adds_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_adds_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vqaddq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_add_saturate(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i16 = vec_adds(a_.altivec_i16, b_.altivec_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + const int_fast32_t tmp = + HEDLEY_STATIC_CAST(int_fast32_t, a_.i16[i]) + + HEDLEY_STATIC_CAST(int_fast32_t, b_.i16[i]); + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, ((tmp < INT16_MAX) ? ((tmp > INT16_MIN) ? tmp : INT16_MIN) : INT16_MAX)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_adds_epi16(a, b) simde_mm_adds_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_adds_epu8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_adds_epu8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vqaddq_u8(a_.neon_u8, b_.neon_u8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u8x16_add_saturate(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + r_.altivec_u8 = vec_adds(a_.altivec_u8, b_.altivec_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = ((UINT8_MAX - a_.u8[i]) > b_.u8[i]) ? (a_.u8[i] + b_.u8[i]) : UINT8_MAX; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_adds_epu8(a, b) simde_mm_adds_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_adds_epu16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_adds_epu16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vqaddq_u16(a_.neon_u16, b_.neon_u16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u16x8_add_saturate(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_u16 = vec_adds(a_.altivec_u16, b_.altivec_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = ((UINT16_MAX - a_.u16[i]) > b_.u16[i]) ? (a_.u16[i] + b_.u16[i]) : UINT16_MAX; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_adds_epu16(a, b) simde_mm_adds_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_and_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_and_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vandq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_and(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + r_.altivec_f64 = vec_and(a_.altivec_f64, b_.altivec_f64); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] & b_.i32f[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_and_pd(a, b) simde_mm_and_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_and_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_and_si128(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vandq_s32(b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_u32f = vec_and(a_.altivec_u32f, b_.altivec_u32f); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] & b_.i32f[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_and_si128(a, b) simde_mm_and_si128(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_andnot_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_andnot_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vbicq_s32(b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_andnot(b_.wasm_v128, a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = vec_andc(b_.altivec_f64, a_.altivec_f64); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32f = vec_andc(b_.altivec_i32f, a_.altivec_i32f); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = ~a_.u64[i] & b_.u64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_andnot_pd(a, b) simde_mm_andnot_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_andnot_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_andnot_si128(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vbicq_s32(b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_andc(b_.altivec_i32, a_.altivec_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~(a_.i32f[i]) & b_.i32f[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_andnot_si128(a, b) simde_mm_andnot_si128(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_xor_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_xor_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_xor(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = veorq_s64(a_.neon_i64, b_.neon_i64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] ^ b_.i32f[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_xor_pd(a, b) simde_mm_xor_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_avg_epu8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_avg_epu8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vrhaddq_u8(b_.neon_u8, a_.neon_u8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u8x16_avgr(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u8 = vec_avg(a_.altivec_u8, b_.altivec_u8); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) && defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_CONVERT_VECTOR_) + uint16_t wa SIMDE_VECTOR(32); + uint16_t wb SIMDE_VECTOR(32); + uint16_t wr SIMDE_VECTOR(32); + SIMDE_CONVERT_VECTOR_(wa, a_.u8); + SIMDE_CONVERT_VECTOR_(wb, b_.u8); + wr = (wa + wb + 1) >> 1; + SIMDE_CONVERT_VECTOR_(r_.u8, wr); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] + b_.u8[i] + 1) >> 1; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_avg_epu8(a, b) simde_mm_avg_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_avg_epu16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_avg_epu16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vrhaddq_u16(b_.neon_u16, a_.neon_u16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u16x8_avgr(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u16 = vec_avg(a_.altivec_u16, b_.altivec_u16); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) && defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && defined(SIMDE_CONVERT_VECTOR_) + uint32_t wa SIMDE_VECTOR(32); + uint32_t wb SIMDE_VECTOR(32); + uint32_t wr SIMDE_VECTOR(32); + SIMDE_CONVERT_VECTOR_(wa, a_.u16); + SIMDE_CONVERT_VECTOR_(wb, b_.u16); + wr = (wa + wb + 1) >> 1; + SIMDE_CONVERT_VECTOR_(r_.u16, wr); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = (a_.u16[i] + b_.u16[i] + 1) >> 1; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_avg_epu16(a, b) simde_mm_avg_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_setzero_si128 (void) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_setzero_si128(); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vdupq_n_s32(0); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_splats(HEDLEY_STATIC_CAST(signed int, 0)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_splat(INT32_C(0)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT) + r_.i32 = __extension__ (__typeof__(r_.i32)) { 0, 0, 0, 0 }; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = 0; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setzero_si128() (simde_mm_setzero_si128()) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_bslli_si128 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + if (HEDLEY_UNLIKELY((imm8 & ~15))) { + return simde_mm_setzero_si128(); + } + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && defined(SIMDE_ENDIAN_ORDER) + r_.altivec_i8 = + #if (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + vec_slo + #else /* SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_BIG */ + vec_sro + #endif + (a_.altivec_i8, vec_splats(HEDLEY_STATIC_CAST(unsigned char, imm8 * 8))); + #elif defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_srb(a_.altivec_i8, vec_splats(HEDLEY_STATIC_CAST(unsigned char, (imm8 & 15) << 3))); + #elif defined(SIMDE_HAVE_INT128_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + r_.u128[0] = a_.u128[0] << (imm8 * 8); + #else + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + for (int i = imm8 ; i < HEDLEY_STATIC_CAST(int, sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i - imm8]; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + #define simde_mm_bslli_si128(a, imm8) _mm_slli_si128(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) && !defined(__clang__) + #define simde_mm_bslli_si128(a, imm8) \ + simde__m128i_from_neon_i8(((imm8) <= 0) ? simde__m128i_to_neon_i8(a) : (((imm8) > 15) ? (vdupq_n_s8(0)) : (vextq_s8(vdupq_n_s8(0), simde__m128i_to_neon_i8(a), 16 - (imm8))))) +#elif defined(SIMDE_SHUFFLE_VECTOR_) && !defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && !defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + #define simde_mm_bslli_si128(a, imm8) (__extension__ ({ \ + const simde__m128i_private simde__tmp_a_ = simde__m128i_to_private(a); \ + const simde__m128i_private simde__tmp_z_ = simde__m128i_to_private(simde_mm_setzero_si128()); \ + simde__m128i_private simde__tmp_r_; \ + if (HEDLEY_UNLIKELY(imm8 > 15)) { \ + simde__tmp_r_ = simde__m128i_to_private(simde_mm_setzero_si128()); \ + } else { \ + simde__tmp_r_.i8 = \ + SIMDE_SHUFFLE_VECTOR_(8, 16, \ + simde__tmp_z_.i8, \ + (simde__tmp_a_).i8, \ + HEDLEY_STATIC_CAST(int8_t, (16 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (17 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (18 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (19 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (20 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (21 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (22 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (23 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (24 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (25 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (26 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (27 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (28 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (29 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (30 - imm8) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (31 - imm8) & 31)); \ + } \ + simde__m128i_from_private(simde__tmp_r_); })) +#endif +#define simde_mm_slli_si128(a, imm8) simde_mm_bslli_si128(a, imm8) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_bslli_si128(a, imm8) simde_mm_bslli_si128(a, imm8) + #define _mm_slli_si128(a, imm8) simde_mm_bslli_si128(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_bsrli_si128 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + if (HEDLEY_UNLIKELY((imm8 & ~15))) { + return simde_mm_setzero_si128(); + } + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && defined(SIMDE_ENDIAN_ORDER) + r_.altivec_i8 = + #if (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + vec_sro + #else /* SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_BIG */ + vec_slo + #endif + (a_.altivec_i8, vec_splats(HEDLEY_STATIC_CAST(unsigned char, imm8 * 8))); + #elif defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_slb(a_.altivec_i8, vec_splats(HEDLEY_STATIC_CAST(unsigned char, (imm8 & 15) << 3))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + const int e = HEDLEY_STATIC_CAST(int, i) + imm8; + r_.i8[i] = (e < 16) ? a_.i8[e] : 0; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + #define simde_mm_bsrli_si128(a, imm8) _mm_srli_si128(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) && !defined(__clang__) + #define simde_mm_bsrli_si128(a, imm8) \ + simde__m128i_from_neon_i8(((imm8 < 0) || (imm8 > 15)) ? vdupq_n_s8(0) : (vextq_s8(simde__m128i_to_private(a).neon_i8, vdupq_n_s8(0), ((imm8 & 15) != 0) ? imm8 : (imm8 & 15)))) +#elif defined(SIMDE_SHUFFLE_VECTOR_) && !defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && !defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + #define simde_mm_bsrli_si128(a, imm8) (__extension__ ({ \ + const simde__m128i_private simde__tmp_a_ = simde__m128i_to_private(a); \ + const simde__m128i_private simde__tmp_z_ = simde__m128i_to_private(simde_mm_setzero_si128()); \ + simde__m128i_private simde__tmp_r_ = simde__m128i_to_private(a); \ + if (HEDLEY_UNLIKELY(imm8 > 15)) { \ + simde__tmp_r_ = simde__m128i_to_private(simde_mm_setzero_si128()); \ + } else { \ + simde__tmp_r_.i8 = \ + SIMDE_SHUFFLE_VECTOR_(8, 16, \ + simde__tmp_z_.i8, \ + (simde__tmp_a_).i8, \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 16) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 17) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 18) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 19) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 20) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 21) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 22) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 23) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 24) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 25) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 26) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 27) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 28) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 29) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 30) & 31), \ + HEDLEY_STATIC_CAST(int8_t, (imm8 + 31) & 31)); \ + } \ + simde__m128i_from_private(simde__tmp_r_); })) +#endif +#define simde_mm_srli_si128(a, imm8) simde_mm_bsrli_si128((a), (imm8)) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_bsrli_si128(a, imm8) simde_mm_bsrli_si128((a), (imm8)) + #define _mm_srli_si128(a, imm8) simde_mm_bsrli_si128((a), (imm8)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_clflush (void const* p) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_clflush(p); + #else + (void) p; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_clflush(a, b) simde_mm_clflush() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comieq_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_comieq_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return !!vgetq_lane_u64(vceqq_f64(a_.neon_f64, b_.neon_f64), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) == wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #else + return a_.f64[0] == b_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_comieq_sd(a, b) simde_mm_comieq_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comige_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_comige_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return !!vgetq_lane_u64(vcgeq_f64(a_.neon_f64, b_.neon_f64), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) >= wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #else + return a_.f64[0] >= b_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_comige_sd(a, b) simde_mm_comige_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comigt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_comigt_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return !!vgetq_lane_u64(vcgtq_f64(a_.neon_f64, b_.neon_f64), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) > wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #else + return a_.f64[0] > b_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_comigt_sd(a, b) simde_mm_comigt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comile_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_comile_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return !!vgetq_lane_u64(vcleq_f64(a_.neon_f64, b_.neon_f64), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) <= wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #else + return a_.f64[0] <= b_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_comile_sd(a, b) simde_mm_comile_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comilt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_comilt_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return !!vgetq_lane_u64(vcltq_f64(a_.neon_f64, b_.neon_f64), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) < wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #else + return a_.f64[0] < b_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_comilt_sd(a, b) simde_mm_comilt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_comineq_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_comineq_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return !vgetq_lane_u64(vceqq_f64(a_.neon_f64, b_.neon_f64), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) != wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #else + return a_.f64[0] != b_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_comineq_sd(a, b) simde_mm_comineq_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_copysign_pd(simde__m128d dest, simde__m128d src) { + simde__m128d_private + r_, + dest_ = simde__m128d_to_private(dest), + src_ = simde__m128d_to_private(src); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t sign_pos = vreinterpretq_u64_f64(vdupq_n_f64(-SIMDE_FLOAT64_C(0.0))); + #else + simde_float64 dbl_nz = -SIMDE_FLOAT64_C(0.0); + uint64_t u64_nz; + simde_memcpy(&u64_nz, &dbl_nz, sizeof(u64_nz)); + uint64x2_t sign_pos = vdupq_n_u64(u64_nz); + #endif + r_.neon_u64 = vbslq_u64(sign_pos, src_.neon_u64, dest_.neon_u64); + #elif defined(SIMDE_POWER_ALTIVEC_P9_NATIVE) + #if !defined(HEDLEY_IBM_VERSION) + r_.altivec_f64 = vec_cpsgn(dest_.altivec_f64, src_.altivec_f64); + #else + r_.altivec_f64 = vec_cpsgn(src_.altivec_f64, dest_.altivec_f64); + #endif + #elif defined(simde_math_copysign) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_copysign(dest_.f64[i], src_.f64[i]); + } + #else + simde__m128d sgnbit = simde_mm_set1_pd(-SIMDE_FLOAT64_C(0.0)); + return simde_mm_xor_pd(simde_mm_and_pd(sgnbit, src), simde_mm_andnot_pd(sgnbit, dest)); + #endif + + return simde__m128d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_xorsign_pd(simde__m128d dest, simde__m128d src) { + return simde_mm_xor_pd(simde_mm_and_pd(simde_mm_set1_pd(-0.0), src), dest); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_castpd_ps (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_castpd_ps(a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vreinterpretq_f32_f64(a); + #else + simde__m128 r; + simde_memcpy(&r, &a, sizeof(a)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_castpd_ps(a) simde_mm_castpd_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_castpd_si128 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_castpd_si128(a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vreinterpretq_s64_f64(a); + #else + simde__m128i r; + simde_memcpy(&r, &a, sizeof(a)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_castpd_si128(a) simde_mm_castpd_si128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_castps_pd (simde__m128 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_castps_pd(a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vreinterpretq_f64_f32(a); + #else + simde__m128d r; + simde_memcpy(&r, &a, sizeof(a)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_castps_pd(a) simde_mm_castps_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_castps_si128 (simde__m128 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_castps_si128(a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return simde__m128i_from_neon_i32(simde__m128_to_private(a).neon_i32); + #else + simde__m128i r; + simde_memcpy(&r, &a, sizeof(a)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_castps_si128(a) simde_mm_castps_si128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_castsi128_pd (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_castsi128_pd(a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vreinterpretq_f64_s64(a); + #else + simde__m128d r; + simde_memcpy(&r, &a, sizeof(a)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_castsi128_pd(a) simde_mm_castsi128_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_castsi128_ps (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_castsi128_ps(a); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + return HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(float), a); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return simde__m128_from_neon_i32(simde__m128i_to_private(a).neon_i32); + #else + simde__m128 r; + simde_memcpy(&r, &a, sizeof(a)); + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_castsi128_ps(a) simde_mm_castsi128_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpeq_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpeq_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vceqq_s8(b_.neon_i8, a_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_eq(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed char), vec_cmpeq(a_.altivec_i8, b_.altivec_i8)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = HEDLEY_STATIC_CAST(__typeof__(r_.i8), (a_.i8 == b_.i8)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] == b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpeq_epi8(a, b) simde_mm_cmpeq_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpeq_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpeq_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vceqq_s16(b_.neon_i16, a_.neon_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_eq(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed short), vec_cmpeq(a_.altivec_i16, b_.altivec_i16)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = (a_.i16 == b_.i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] == b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpeq_epi16(a, b) simde_mm_cmpeq_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpeq_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpeq_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vceqq_s32(b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_eq(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed int), vec_cmpeq(a_.altivec_i32, b_.altivec_i32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), a_.i32 == b_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] == b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpeq_epi32(a, b) simde_mm_cmpeq_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpeq_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpeq_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vceqq_s64(b_.neon_i64, a_.neon_i64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_eq(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_cmpeq(a_.altivec_f64, b_.altivec_f64)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 == b_.f64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (a_.f64[i] == b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpeq_pd(a, b) simde_mm_cmpeq_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpeq_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpeq_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmpeq_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.u64[0] = (a_.u64[0] == b_.u64[0]) ? ~UINT64_C(0) : 0; + r_.u64[1] = a_.u64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpeq_sd(a, b) simde_mm_cmpeq_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpneq_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpneq_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u32 = vmvnq_u32(vreinterpretq_u32_u64(vceqq_f64(b_.neon_f64, a_.neon_f64))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_ne(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 != b_.f64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (a_.f64[i] != b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpneq_pd(a, b) simde_mm_cmpneq_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpneq_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpneq_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmpneq_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.u64[0] = (a_.f64[0] != b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpneq_sd(a, b) simde_mm_cmpneq_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmplt_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmplt_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vcltq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed char),vec_cmplt(a_.altivec_i8, b_.altivec_i8)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_lt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = HEDLEY_STATIC_CAST(__typeof__(r_.i8), (a_.i8 < b_.i8)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] < b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmplt_epi8(a, b) simde_mm_cmplt_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmplt_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmplt_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vcltq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed short), vec_cmplt(a_.altivec_i16, b_.altivec_i16)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_lt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = HEDLEY_STATIC_CAST(__typeof__(r_.i16), (a_.i16 < b_.i16)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] < b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmplt_epi16(a, b) simde_mm_cmplt_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmplt_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmplt_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcltq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed int), vec_cmplt(a_.altivec_i32, b_.altivec_i32)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_lt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.i32 < b_.i32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] < b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmplt_epi32(a, b) simde_mm_cmplt_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmplt_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmplt_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vcltq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_cmplt(a_.altivec_f64, b_.altivec_f64)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_lt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 < b_.f64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (a_.f64[i] < b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmplt_pd(a, b) simde_mm_cmplt_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmplt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmplt_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmplt_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.u64[0] = (a_.f64[0] < b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmplt_sd(a, b) simde_mm_cmplt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmple_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmple_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 <= b_.f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vcleq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_le(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_cmple(a_.altivec_f64, b_.altivec_f64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (a_.f64[i] <= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmple_pd(a, b) simde_mm_cmple_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmple_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmple_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmple_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.u64[0] = (a_.f64[0] <= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmple_sd(a, b) simde_mm_cmple_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpgt_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpgt_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vcgtq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_gt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed char), vec_cmpgt(a_.altivec_i8, b_.altivec_i8)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = HEDLEY_STATIC_CAST(__typeof__(r_.i8), (a_.i8 > b_.i8)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] > b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpgt_epi8(a, b) simde_mm_cmpgt_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpgt_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpgt_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vcgtq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_gt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed short), vec_cmpgt(a_.altivec_i16, b_.altivec_i16)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = HEDLEY_STATIC_CAST(__typeof__(r_.i16), (a_.i16 > b_.i16)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] > b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpgt_epi16(a, b) simde_mm_cmpgt_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpgt_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpgt_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vcgtq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_gt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed int), vec_cmpgt(a_.altivec_i32, b_.altivec_i32)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.i32 > b_.i32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] > b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpgt_epi32(a, b) simde_mm_cmpgt_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpgt_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpgt_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 > b_.f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vcgtq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_gt(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_STATIC_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_cmpgt(a_.altivec_f64, b_.altivec_f64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (a_.f64[i] > b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpgt_pd(a, b) simde_mm_cmpgt_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpgt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + return _mm_cmpgt_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmpgt_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.u64[0] = (a_.f64[0] > b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpgt_sd(a, b) simde_mm_cmpgt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpge_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpge_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 >= b_.f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vcgeq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_ge(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_STATIC_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_cmpge(a_.altivec_f64, b_.altivec_f64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (a_.f64[i] >= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpge_pd(a, b) simde_mm_cmpge_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpge_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + return _mm_cmpge_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmpge_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.u64[0] = (a_.f64[0] >= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpge_sd(a, b) simde_mm_cmpge_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpngt_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpngt_pd(a, b); + #else + return simde_mm_cmple_pd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpngt_pd(a, b) simde_mm_cmpngt_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpngt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + return _mm_cmpngt_sd(a, b); + #else + return simde_mm_cmple_sd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpngt_sd(a, b) simde_mm_cmpngt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpnge_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpnge_pd(a, b); + #else + return simde_mm_cmplt_pd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpnge_pd(a, b) simde_mm_cmpnge_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpnge_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + return _mm_cmpnge_sd(a, b); + #else + return simde_mm_cmplt_sd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpnge_sd(a, b) simde_mm_cmpnge_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpnlt_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpnlt_pd(a, b); + #else + return simde_mm_cmpge_pd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpnlt_pd(a, b) simde_mm_cmpnlt_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpnlt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpnlt_sd(a, b); + #else + return simde_mm_cmpge_sd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpnlt_sd(a, b) simde_mm_cmpnlt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpnle_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpnle_pd(a, b); + #else + return simde_mm_cmpgt_pd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpnle_pd(a, b) simde_mm_cmpnle_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpnle_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpnle_sd(a, b); + #else + return simde_mm_cmpgt_sd(a, b); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpnle_sd(a, b) simde_mm_cmpnle_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpord_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpord_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + /* Note: NEON does not have ordered compare builtin + Need to compare a eq a and b eq b to check for NaN + Do AND of results to get final */ + uint64x2_t ceqaa = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t ceqbb = vceqq_f64(b_.neon_f64, b_.neon_f64); + r_.neon_u64 = vandq_u64(ceqaa, ceqbb); + #elif defined(simde_math_isnan) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (!simde_math_isnan(a_.f64[i]) && !simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpord_pd(a, b) simde_mm_cmpord_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde_float64 +simde_mm_cvtsd_f64 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + return _mm_cvtsd_f64(a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return HEDLEY_STATIC_CAST(simde_float64, vgetq_lane_f64(a_.neon_f64, 0)); + #else + return a_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtsd_f64(a) simde_mm_cvtsd_f64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpord_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpord_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmpord_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(simde_math_isnan) + r_.u64[0] = (!simde_math_isnan(a_.f64[0]) && !simde_math_isnan(b_.f64[0])) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpord_sd(a, b) simde_mm_cmpord_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpunord_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpunord_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t ceqaa = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t ceqbb = vceqq_f64(b_.neon_f64, b_.neon_f64); + r_.neon_u64 = vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(vandq_u64(ceqaa, ceqbb)))); + #elif defined(simde_math_isnan) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpunord_pd(a, b) simde_mm_cmpunord_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmpunord_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cmpunord_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_cmpunord_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(simde_math_isnan) + r_.u64[0] = (simde_math_isnan(a_.f64[0]) || simde_math_isnan(b_.f64[0])) ? ~UINT64_C(0) : UINT64_C(0); + r_.u64[1] = a_.u64[1]; + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cmpunord_sd(a, b) simde_mm_cmpunord_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cvtepi32_pd (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtepi32_pd(a); + #else + simde__m128d_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.f64, a_.m64_private[0].i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = (simde_float64) a_.i32[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtepi32_pd(a) simde_mm_cvtepi32_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtepi32_ps (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtepi32_ps(a); + #else + simde__m128_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_f32 = vcvtq_f32_s32(a_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f32x4_convert_i32x4(a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + HEDLEY_DIAGNOSTIC_PUSH + #if HEDLEY_HAS_WARNING("-Wc11-extensions") + #pragma clang diagnostic ignored "-Wc11-extensions" + #endif + r_.altivec_f32 = vec_ctf(a_.altivec_i32, 0); + HEDLEY_DIAGNOSTIC_POP + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.f32, a_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (simde_float32) a_.i32[i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtepi32_ps(a) simde_mm_cvtepi32_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvtpd_pi32 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpd_pi32(a); + #else + simde__m64_private r_; + simde__m128d_private a_ = simde__m128d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + simde_float64 v = simde_math_round(a_.f64[i]); + #if defined(SIMDE_FAST_CONVERSION_RANGE) + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, v); + #else + r_.i32[i] = ((v > HEDLEY_STATIC_CAST(simde_float64, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float64, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #endif + } + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtpd_pi32(a) simde_mm_cvtpd_pi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtpd_epi32 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtpd_epi32(a); + #else + simde__m128i_private r_; + + r_.m64[0] = simde_mm_cvtpd_pi32(a); + r_.m64[1] = simde_mm_setzero_si64(); + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtpd_epi32(a) simde_mm_cvtpd_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtpd_ps (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtpd_ps(a); + #else + simde__m128_private r_; + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.m64_private[0].f32, a_.f64); + r_.m64_private[1] = simde__m64_to_private(simde_mm_setzero_si64()); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vreinterpretq_f32_f64(vcombine_f64(vreinterpret_f64_f32(vcvtx_f32_f64(a_.neon_f64)), vdup_n_f64(0))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f64) / sizeof(a_.f64[0])) ; i++) { + r_.f32[i] = (simde_float32) a_.f64[i]; + } + simde_memset(&(r_.m64_private[1]), 0, sizeof(r_.m64_private[1])); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtpd_ps(a) simde_mm_cvtpd_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cvtpi32_pd (simde__m64 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvtpi32_pd(a); + #else + simde__m128d_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.f64, a_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = (simde_float64) a_.i32[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtpi32_pd(a) simde_mm_cvtpi32_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtps_epi32 (simde__m128 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtps_epi32(a); + #else + simde__m128i_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) + r_.neon_i32 = vcvtnq_s32_f32(a_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) && defined(SIMDE_FAST_ROUND_TIES) && !defined(SIMDE_BUG_GCC_95399) + r_.neon_i32 = vcvtnq_s32_f32(a_.neon_f32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) && defined(SIMDE_FAST_ROUND_TIES) + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_C11_EXTENSIONS_ + SIMDE_DIAGNOSTIC_DISABLE_VECTOR_CONVERSION_ + r_.altivec_i32 = vec_cts(a_.altivec_f32, 1); + HEDLEY_DIAGNOSTIC_POP + #else + a_ = simde__m128_to_private(simde_x_mm_round_ps(a, SIMDE_MM_FROUND_TO_NEAREST_INT, 1)); + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + simde_float32 v = simde_math_roundf(a_.f32[i]); + #if defined(SIMDE_FAST_CONVERSION_RANGE) + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, v); + #else + r_.i32[i] = ((v > HEDLEY_STATIC_CAST(simde_float32, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float32, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #endif + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtps_epi32(a) simde_mm_cvtps_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cvtps_pd (simde__m128 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtps_pd(a); + #else + simde__m128d_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.f64, a_.m64_private[0].f32); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vcvt_f64_f32(vget_low_f32(a_.neon_f32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f32[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtps_pd(a) simde_mm_cvtps_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvtsd_si32 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtsd_si32(a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + + simde_float64 v = simde_math_round(a_.f64[0]); + #if defined(SIMDE_FAST_CONVERSION_RANGE) + return SIMDE_CONVERT_FTOI(int32_t, v); + #else + return ((v > HEDLEY_STATIC_CAST(simde_float64, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float64, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtsd_si32(a) simde_mm_cvtsd_si32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_cvtsd_si64 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if defined(__PGI) + return _mm_cvtsd_si64x(a); + #else + return _mm_cvtsd_si64(a); + #endif + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + return SIMDE_CONVERT_FTOI(int64_t, simde_math_round(a_.f64[0])); + #endif +} +#define simde_mm_cvtsd_si64x(a) simde_mm_cvtsd_si64(a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_cvtsd_si64(a) simde_mm_cvtsd_si64(a) + #define _mm_cvtsd_si64x(a) simde_mm_cvtsd_si64x(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cvtsd_ss (simde__m128 a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtsd_ss(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + simde__m128d_private b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vsetq_lane_f32(vcvtxd_f32_f64(vgetq_lane_f64(b_.neon_f64, 0)), a_.neon_f32, 0); + #else + r_.f32[0] = HEDLEY_STATIC_CAST(simde_float32, b_.f64[0]); + + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i]; + } + #endif + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtsd_ss(a, b) simde_mm_cvtsd_ss(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int16_t +simde_x_mm_cvtsi128_si16 (simde__m128i a) { + simde__m128i_private + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vgetq_lane_s16(a_.neon_i16, 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return HEDLEY_STATIC_CAST(int16_t, wasm_i16x8_extract_lane(a_.wasm_v128, 0)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + #endif + return vec_extract(a_.altivec_i16, 0); + #else + return a_.i16[0]; + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvtsi128_si32 (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtsi128_si32(a); + #else + simde__m128i_private + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vgetq_lane_s32(a_.neon_i32, 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return HEDLEY_STATIC_CAST(int32_t, wasm_i32x4_extract_lane(a_.wasm_v128, 0)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + #endif + return vec_extract(a_.altivec_i32, 0); + #else + return a_.i32[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtsi128_si32(a) simde_mm_cvtsi128_si32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_cvtsi128_si64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if defined(__PGI) + return _mm_cvtsi128_si64x(a); + #else + return _mm_cvtsi128_si64(a); + #endif + #else + simde__m128i_private a_ = simde__m128i_to_private(a); + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) && !defined(HEDLEY_IBM_VERSION) + return vec_extract(HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed long long), a_.i64), 0); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vgetq_lane_s64(a_.neon_i64, 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return HEDLEY_STATIC_CAST(int64_t, wasm_i64x2_extract_lane(a_.wasm_v128, 0)); + #endif + return a_.i64[0]; + #endif +} +#define simde_mm_cvtsi128_si64x(a) simde_mm_cvtsi128_si64(a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_cvtsi128_si64(a) simde_mm_cvtsi128_si64(a) + #define _mm_cvtsi128_si64x(a) simde_mm_cvtsi128_si64x(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cvtsi32_sd (simde__m128d a, int32_t b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtsi32_sd(a, b); + #else + simde__m128d_private r_; + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vsetq_lane_f64(HEDLEY_STATIC_CAST(float64_t, b), a_.neon_f64, 0); + #else + r_.f64[0] = HEDLEY_STATIC_CAST(simde_float64, b); + r_.i64[1] = a_.i64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtsi32_sd(a, b) simde_mm_cvtsi32_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_cvtsi16_si128 (int16_t a) { + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vsetq_lane_s16(a, vdupq_n_s16(0), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_make(a, 0, 0, 0, 0, 0, 0, 0); + #else + r_.i16[0] = a; + r_.i16[1] = 0; + r_.i16[2] = 0; + r_.i16[3] = 0; + r_.i16[4] = 0; + r_.i16[5] = 0; + r_.i16[6] = 0; + r_.i16[7] = 0; + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtsi32_si128 (int32_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtsi32_si128(a); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vsetq_lane_s32(a, vdupq_n_s32(0), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_make(a, 0, 0, 0); + #else + r_.i32[0] = a; + r_.i32[1] = 0; + r_.i32[2] = 0; + r_.i32[3] = 0; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtsi32_si128(a) simde_mm_cvtsi32_si128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cvtsi64_sd (simde__m128d a, int64_t b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if !defined(__PGI) + return _mm_cvtsi64_sd(a, b); + #else + return _mm_cvtsi64x_sd(a, b); + #endif + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vsetq_lane_f64(HEDLEY_STATIC_CAST(float64_t, b), a_.neon_f64, 0); + #else + r_.f64[0] = HEDLEY_STATIC_CAST(simde_float64, b); + r_.f64[1] = a_.f64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#define simde_mm_cvtsi64x_sd(a, b) simde_mm_cvtsi64_sd(a, b) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_cvtsi64_sd(a, b) simde_mm_cvtsi64_sd(a, b) + #define _mm_cvtsi64x_sd(a, b) simde_mm_cvtsi64x_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtsi64_si128 (int64_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if !defined(__PGI) + return _mm_cvtsi64_si128(a); + #else + return _mm_cvtsi64x_si128(a); + #endif + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vsetq_lane_s64(a, vdupq_n_s64(0), 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i64x2_make(a, 0); + #else + r_.i64[0] = a; + r_.i64[1] = 0; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#define simde_mm_cvtsi64x_si128(a) simde_mm_cvtsi64_si128(a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_cvtsi64_si128(a) simde_mm_cvtsi64_si128(a) + #define _mm_cvtsi64x_si128(a) simde_mm_cvtsi64x_si128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cvtss_sd (simde__m128d a, simde__m128 b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvtss_sd(a, b); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x2_t temp = vcvt_f64_f32(vset_lane_f32(vgetq_lane_f32(simde__m128_to_private(b).neon_f32, 0), vdup_n_f32(0), 0)); + return vsetq_lane_f64(vgetq_lane_f64(simde__m128d_to_private(a).neon_f64, 1), temp, 1); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a); + simde__m128_private b_ = simde__m128_to_private(b); + + a_.f64[0] = HEDLEY_STATIC_CAST(simde_float64, b_.f32[0]); + + return simde__m128d_from_private(a_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvtss_sd(a, b) simde_mm_cvtss_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_cvttpd_pi32 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_cvttpd_pi32(a); + #else + simde__m64_private r_; + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) && defined(SIMDE_FAST_CONVERSION_RANGE) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.f64); + #else + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + simde_float64 v = a_.f64[i]; + #if defined(SIMDE_FAST_CONVERSION_RANGE) + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, v); + #else + r_.i32[i] = ((v > HEDLEY_STATIC_CAST(simde_float64, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float64, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #endif + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvttpd_pi32(a) simde_mm_cvttpd_pi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvttpd_epi32 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvttpd_epi32(a); + #else + simde__m128i_private r_; + + r_.m64[0] = simde_mm_cvttpd_pi32(a); + r_.m64[1] = simde_mm_setzero_si64(); + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvttpd_epi32(a) simde_mm_cvttpd_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvttps_epi32 (simde__m128 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvttps_epi32(a); + #else + simde__m128i_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) && defined(SIMDE_FAST_CONVERSION_RANGE) + r_.neon_i32 = vcvtq_s32_f32(a_.neon_f32); + #elif defined(SIMDE_CONVERT_VECTOR_) && defined(SIMDE_FAST_CONVERSION_RANGE) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.f32); + #else + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + simde_float32 v = a_.f32[i]; + #if defined(SIMDE_FAST_CONVERSION_RANGE) + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, v); + #else + r_.i32[i] = ((v > HEDLEY_STATIC_CAST(simde_float32, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float32, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #endif + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvttps_epi32(a) simde_mm_cvttps_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_cvttsd_si32 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_cvttsd_si32(a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + simde_float64 v = a_.f64[0]; + #if defined(SIMDE_FAST_CONVERSION_RANGE) + return SIMDE_CONVERT_FTOI(int32_t, v); + #else + return ((v > HEDLEY_STATIC_CAST(simde_float64, INT32_MIN)) && (v < HEDLEY_STATIC_CAST(simde_float64, INT32_MAX))) ? + SIMDE_CONVERT_FTOI(int32_t, v) : INT32_MIN; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_cvttsd_si32(a) simde_mm_cvttsd_si32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_cvttsd_si64 (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if !defined(__PGI) + return _mm_cvttsd_si64(a); + #else + return _mm_cvttsd_si64x(a); + #endif + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + return SIMDE_CONVERT_FTOI(int64_t, a_.f64[0]); + #endif +} +#define simde_mm_cvttsd_si64x(a) simde_mm_cvttsd_si64(a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_cvttsd_si64(a) simde_mm_cvttsd_si64(a) + #define _mm_cvttsd_si64x(a) simde_mm_cvttsd_si64x(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_div_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_div_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 / b_.f64; + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vdivq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_div(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] / b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_div_pd(a, b) simde_mm_div_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_div_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_div_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_div_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x2_t temp = vdivq_f64(a_.neon_f64, b_.neon_f64); + r_.neon_f64 = vsetq_lane_f64(vgetq_lane(a_.neon_f64, 1), temp, 1); + #else + r_.f64[0] = a_.f64[0] / b_.f64[0]; + r_.f64[1] = a_.f64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_div_sd(a, b) simde_mm_div_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_extract_epi16 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 7) { + uint16_t r; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + (void) imm8; + #endif + r = HEDLEY_STATIC_CAST(uint16_t, vec_extract(a_.altivec_i16, imm8)); + #else + r = a_.u16[imm8 & 7]; + #endif + + return HEDLEY_STATIC_CAST(int32_t, r); +} +#if defined(SIMDE_X86_SSE2_NATIVE) && (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(4,6,0)) + #define simde_mm_extract_epi16(a, imm8) _mm_extract_epi16(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_extract_epi16(a, imm8) (HEDLEY_STATIC_CAST(int32_t, vgetq_lane_s16(simde__m128i_to_private(a).neon_i16, (imm8))) & (INT32_C(0x0000ffff))) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_extract_epi16(a, imm8) simde_mm_extract_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_insert_epi16 (simde__m128i a, int16_t i, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 7) { + simde__m128i_private a_ = simde__m128i_to_private(a); + a_.i16[imm8 & 7] = i; + return simde__m128i_from_private(a_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + #define simde_mm_insert_epi16(a, i, imm8) _mm_insert_epi16((a), (i), (imm8)) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_insert_epi16(a, i, imm8) simde__m128i_from_neon_i16(vsetq_lane_s16((i), simde__m128i_to_neon_i16(a), (imm8))) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_insert_epi16(a, i, imm8) simde_mm_insert_epi16(a, i, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_load_pd (simde_float64 const mem_addr[HEDLEY_ARRAY_PARAM(2)]) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_load_pd(mem_addr); + #else + simde__m128d_private r_; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vld1q_f64(mem_addr); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vld1q_u32(HEDLEY_REINTERPRET_CAST(uint32_t const*, mem_addr)); + #else + simde_memcpy(&r_, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m128d), sizeof(r_)); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_load_pd(mem_addr) simde_mm_load_pd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_load1_pd (simde_float64 const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_load1_pd(mem_addr); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return simde__m128d_from_neon_f64(vld1q_dup_f64(mem_addr)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return simde__m128d_from_wasm_v128(wasm_v64x2_load_splat(mem_addr)); + #else + return simde_mm_set1_pd(*mem_addr); + #endif +} +#define simde_mm_load_pd1(mem_addr) simde_mm_load1_pd(mem_addr) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_load_pd1(mem_addr) simde_mm_load1_pd(mem_addr) + #define _mm_load1_pd(mem_addr) simde_mm_load1_pd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_load_sd (simde_float64 const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_load_sd(mem_addr); + #else + simde__m128d_private r_; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vsetq_lane_f64(*mem_addr, vdupq_n_f64(0), 0); + #else + r_.f64[0] = *mem_addr; + r_.u64[1] = UINT64_C(0); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_load_sd(mem_addr) simde_mm_load_sd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_load_si128 (simde__m128i const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_load_si128(HEDLEY_REINTERPRET_CAST(__m128i const*, mem_addr)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_ld(0, HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(int) const*, mem_addr)); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vld1q_s32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr)); + #else + simde_memcpy(&r_, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m128i), sizeof(simde__m128i)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_load_si128(mem_addr) simde_mm_load_si128(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_loadh_pd (simde__m128d a, simde_float64 const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadh_pd(a, mem_addr); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vcombine_f64(vget_low_f64(a_.neon_f64), vld1_f64(HEDLEY_REINTERPRET_CAST(const float64_t*, mem_addr))); + #else + simde_float64 t; + + simde_memcpy(&t, mem_addr, sizeof(t)); + r_.f64[0] = a_.f64[0]; + r_.f64[1] = t; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadh_pd(a, mem_addr) simde_mm_loadh_pd(a, mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadl_epi64 (simde__m128i const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadl_epi64(mem_addr); + #else + simde__m128i_private r_; + + int64_t value; + simde_memcpy(&value, mem_addr, sizeof(value)); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vcombine_s64(vld1_s64(HEDLEY_REINTERPRET_CAST(int64_t const *, mem_addr)), vdup_n_s64(0)); + #else + r_.i64[0] = value; + r_.i64[1] = 0; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadl_epi64(mem_addr) simde_mm_loadl_epi64(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_loadl_pd (simde__m128d a, simde_float64 const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadl_pd(a, mem_addr); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vcombine_f64(vld1_f64( + HEDLEY_REINTERPRET_CAST(const float64_t*, mem_addr)), vget_high_f64(a_.neon_f64)); + #else + r_.f64[0] = *mem_addr; + r_.u64[1] = a_.u64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadl_pd(a, mem_addr) simde_mm_loadl_pd(a, mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_loadr_pd (simde_float64 const mem_addr[HEDLEY_ARRAY_PARAM(2)]) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadr_pd(mem_addr); + #else + simde__m128d_private + r_; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vld1q_f64(mem_addr); + r_.neon_f64 = vextq_f64(r_.neon_f64, r_.neon_f64, 1); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vld1q_s64(HEDLEY_REINTERPRET_CAST(int64_t const *, mem_addr)); + r_.neon_i64 = vextq_s64(r_.neon_i64, r_.neon_i64, 1); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t tmp = wasm_v128_load(mem_addr); + r_.wasm_v128 = wasm_v64x2_shuffle(tmp, tmp, 1, 0); + #else + r_.f64[0] = mem_addr[1]; + r_.f64[1] = mem_addr[0]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadr_pd(mem_addr) simde_mm_loadr_pd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_loadu_pd (simde_float64 const mem_addr[HEDLEY_ARRAY_PARAM(2)]) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadu_pd(mem_addr); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vld1q_f64(mem_addr); + #else + simde__m128d_private r_; + + simde_memcpy(&r_, mem_addr, sizeof(r_)); + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadu_pd(mem_addr) simde_mm_loadu_pd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_epi8(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm_loadu_epi8(mem_addr); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr)); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#define simde_x_mm_loadu_epi8(mem_addr) simde_mm_loadu_epi8(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm_loadu_epi8 + #define _mm_loadu_epi8(a) simde_mm_loadu_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_epi16(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm_loadu_epi16(mem_addr); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vreinterpretq_s16_s8(vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr))); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#define simde_x_mm_loadu_epi16(mem_addr) simde_mm_loadu_epi16(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm_loadu_epi16 + #define _mm_loadu_epi16(a) simde_mm_loadu_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_epi32(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm_loadu_epi32(mem_addr); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vreinterpretq_s32_s8(vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr))); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#define simde_x_mm_loadu_epi32(mem_addr) simde_mm_loadu_epi32(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm_loadu_epi32 + #define _mm_loadu_epi32(a) simde_mm_loadu_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_epi64(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm_loadu_epi64(mem_addr); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vreinterpretq_s64_s8(vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr))); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#define simde_x_mm_loadu_epi64(mem_addr) simde_mm_loadu_epi64(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm_loadu_epi64 + #define _mm_loadu_epi64(a) simde_mm_loadu_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_si128 (void const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_loadu_si128(HEDLEY_STATIC_CAST(__m128i const*, mem_addr)); + #else + simde__m128i_private r_; + + #if HEDLEY_GNUC_HAS_ATTRIBUTE(may_alias,3,3,0) + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_PACKED_ + struct simde_mm_loadu_si128_s { + __typeof__(r_) v; + } __attribute__((__packed__, __may_alias__)); + r_ = HEDLEY_REINTERPRET_CAST(const struct simde_mm_loadu_si128_s *, mem_addr)->v; + HEDLEY_DIAGNOSTIC_POP + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr)); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadu_si128(mem_addr) simde_mm_loadu_si128(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_madd_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_madd_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + int32x4_t pl = vmull_s16(vget_low_s16(a_.neon_i16), vget_low_s16(b_.neon_i16)); + int32x4_t ph = vmull_high_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i32 = vpaddq_s32(pl, ph); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4_t pl = vmull_s16(vget_low_s16(a_.neon_i16), vget_low_s16(b_.neon_i16)); + int32x4_t ph = vmull_s16(vget_high_s16(a_.neon_i16), vget_high_s16(b_.neon_i16)); + int32x2_t rl = vpadd_s32(vget_low_s32(pl), vget_high_s32(pl)); + int32x2_t rh = vpadd_s32(vget_low_s32(ph), vget_high_s32(ph)); + r_.neon_i32 = vcombine_s32(rl, rh); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + static const SIMDE_POWER_ALTIVEC_VECTOR(int) tz = { 0, 0, 0, 0 }; + r_.altivec_i32 = vec_msum(a_.altivec_i16, b_.altivec_i16, tz); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i16[0])) ; i += 2) { + r_.i32[i / 2] = (a_.i16[i] * b_.i16[i]) + (a_.i16[i + 1] * b_.i16[i + 1]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_madd_epi16(a, b) simde_mm_madd_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_maskmoveu_si128 (simde__m128i a, simde__m128i mask, int8_t mem_addr[HEDLEY_ARRAY_PARAM(16)]) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_maskmoveu_si128(a, mask, HEDLEY_REINTERPRET_CAST(char*, mem_addr)); + #else + simde__m128i_private + a_ = simde__m128i_to_private(a), + mask_ = simde__m128i_to_private(mask); + + for (size_t i = 0 ; i < (sizeof(a_.i8) / sizeof(a_.i8[0])) ; i++) { + if (mask_.u8[i] & 0x80) { + mem_addr[i] = a_.i8[i]; + } + } + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_maskmoveu_si128(a, mask, mem_addr) simde_mm_maskmoveu_si128((a), (mask), SIMDE_CHECKED_REINTERPRET_CAST(int8_t*, char*, (mem_addr))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_movemask_epi8 (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__INTEL_COMPILER) + /* ICC has trouble with _mm_movemask_epi8 at -O2 and above: */ + return _mm_movemask_epi8(a); + #else + int32_t r = 0; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + // Use increasingly wide shifts+adds to collect the sign bits + // together. + // Since the widening shifts would be rather confusing to follow in little endian, everything + // will be illustrated in big endian order instead. This has a different result - the bits + // would actually be reversed on a big endian machine. + + // Starting input (only half the elements are shown): + // 89 ff 1d c0 00 10 99 33 + uint8x16_t input = a_.neon_u8; + + // Shift out everything but the sign bits with an unsigned shift right. + // + // Bytes of the vector:: + // 89 ff 1d c0 00 10 99 33 + // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7) + // | | | | | | | | + // 01 01 00 01 00 00 01 00 + // + // Bits of first important lane(s): + // 10001001 (89) + // \______ + // | + // 00000001 (01) + uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7)); + + // Merge the even lanes together with a 16-bit unsigned shift right + add. + // 'xx' represents garbage data which will be ignored in the final result. + // In the important bytes, the add functions like a binary OR. + // + // 01 01 00 01 00 00 01 00 + // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7)) + // \| \| \| \| + // xx 03 xx 01 xx 00 xx 02 + // + // 00000001 00000001 (01 01) + // \_______ | + // \| + // xxxxxxxx xxxxxx11 (xx 03) + uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7)); + + // Repeat with a wider 32-bit shift + add. + // xx 03 xx 01 xx 00 xx 02 + // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >> 14)) + // \| \| + // xx xx xx 0d xx xx xx 02 + // + // 00000011 00000001 (03 01) + // \\_____ || + // '----.\|| + // xxxxxxxx xxxx1101 (xx 0d) + uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); + + // Last, an even wider 64-bit shift + add to get our result in the low 8 bit lanes. + // xx xx xx 0d xx xx xx 02 + // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >> 28)) + // \| + // xx xx xx xx xx xx xx d2 + // + // 00001101 00000010 (0d 02) + // \ \___ | | + // '---. \| | + // xxxxxxxx 11010010 (xx d2) + uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); + + // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts. + // xx xx xx xx xx xx xx d2 + // || return paired64[0] + // d2 + // Note: Little endian would return the correct value 4b (01001011) instead. + r = vgetq_lane_u8(paired64, 0) | (HEDLEY_STATIC_CAST(int32_t, vgetq_lane_u8(paired64, 8)) << 8); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && !defined(HEDLEY_IBM_VERSION) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + static const SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) perm = { 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0 }; + r = HEDLEY_STATIC_CAST(int32_t, vec_extract(vec_vbpermq(a_.altivec_u8, perm), 1)); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && !defined(HEDLEY_IBM_VERSION) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_BIG) + static const SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) perm = { 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0 }; + r = HEDLEY_STATIC_CAST(int32_t, vec_extract(vec_vbpermq(a_.altivec_u8, perm), 14)); + #else + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u8) / sizeof(a_.u8[0])) ; i++) { + r |= (a_.u8[15 - i] >> 7) << (15 - i); + } + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_movemask_epi8(a) simde_mm_movemask_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_movemask_pd (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_movemask_pd(a); + #else + int32_t r = 0; + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + static const int64_t shift_amount[] = { 0, 1 }; + const int64x2_t shift = vld1q_s64(shift_amount); + uint64x2_t tmp = vshrq_n_u64(a_.neon_u64, 63); + return HEDLEY_STATIC_CAST(int32_t, vaddvq_u64(vshlq_u64(tmp, shift))); + #else + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + r |= (a_.u64[i] >> 63) << i; + } + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_movemask_pd(a) simde_mm_movemask_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_movepi64_pi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_movepi64_pi64(a); + #else + simde__m64_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i64 = vget_low_s64(a_.neon_i64); + #else + r_.i64[0] = a_.i64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_movepi64_pi64(a) simde_mm_movepi64_pi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_movpi64_epi64 (simde__m64 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_movpi64_epi64(a); + #else + simde__m128i_private r_; + simde__m64_private a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vcombine_s64(a_.neon_i64, vdup_n_s64(0)); + #else + r_.i64[0] = a_.i64[0]; + r_.i64[1] = 0; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_movpi64_epi64(a) simde_mm_movpi64_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_min_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_min_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vminq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_min(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = vec_min(a_.altivec_i16, b_.altivec_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] < b_.i16[i]) ? a_.i16[i] : b_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_min_epi16(a, b) simde_mm_min_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_min_epu8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_min_epu8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vminq_u8(a_.neon_u8, b_.neon_u8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u8x16_min(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u8 = vec_min(a_.altivec_u8, b_.altivec_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] < b_.u8[i]) ? a_.u8[i] : b_.u8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_min_epu8(a, b) simde_mm_min_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_min_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_min_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = vec_min(a_.altivec_f64, b_.altivec_f64); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vminq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_min(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = (a_.f64[i] < b_.f64[i]) ? a_.f64[i] : b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_min_pd(a, b) simde_mm_min_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_min_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_min_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_min_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x2_t temp = vminq_f64(a_.neon_f64, b_.neon_f64); + r_.neon_f64 = vsetq_lane_f64(vgetq_lane(a_.neon_f64, 1), temp, 1); + #else + r_.f64[0] = (a_.f64[0] < b_.f64[0]) ? a_.f64[0] : b_.f64[0]; + r_.f64[1] = a_.f64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_min_sd(a, b) simde_mm_min_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_max_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_max_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vmaxq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = vec_max(a_.altivec_i16, b_.altivec_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] > b_.i16[i]) ? a_.i16[i] : b_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_max_epi16(a, b) simde_mm_max_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_max_epu8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_max_epu8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vmaxq_u8(a_.neon_u8, b_.neon_u8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u8x16_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u8 = vec_max(a_.altivec_u8, b_.altivec_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] > b_.u8[i]) ? a_.u8[i] : b_.u8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_max_epu8(a, b) simde_mm_max_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_max_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_max_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = vec_max(a_.altivec_f64, b_.altivec_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vmaxq_f64(a_.neon_f64, b_.neon_f64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = (a_.f64[i] > b_.f64[i]) ? a_.f64[i] : b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_max_pd(a, b) simde_mm_max_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_max_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_max_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_max_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x2_t temp = vmaxq_f64(a_.neon_f64, b_.neon_f64); + r_.neon_f64 = vsetq_lane_f64(vgetq_lane(a_.neon_f64, 1), temp, 1); + #else + r_.f64[0] = (a_.f64[0] > b_.f64[0]) ? a_.f64[0] : b_.f64[0]; + r_.f64[1] = a_.f64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_max_sd(a, b) simde_mm_max_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_move_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_move_epi64(a); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vsetq_lane_s64(0, a_.neon_i64, 1); + #else + r_.i64[0] = a_.i64[0]; + r_.i64[1] = 0; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_move_epi64(a) simde_mm_move_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mul_epu32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_mul_epu32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x2_t a_lo = vmovn_u64(a_.neon_u64); + uint32x2_t b_lo = vmovn_u64(b_.neon_u64); + r_.neon_u64 = vmull_u32(a_lo, b_lo); + #elif defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(a_.u32) z = { 0, }; + a_.u32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.u32, z, 0, 4, 2, 6); + b_.u32 = SIMDE_SHUFFLE_VECTOR_(32, 16, b_.u32, z, 0, 4, 2, 6); + r_.u64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.u64), a_.u32) * + HEDLEY_REINTERPRET_CAST(__typeof__(r_.u64), b_.u32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = HEDLEY_STATIC_CAST(uint64_t, a_.u32[i * 2]) * HEDLEY_STATIC_CAST(uint64_t, b_.u32[i * 2]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mul_epu32(a, b) simde_mm_mul_epu32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_mul_epi64 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 * b_.i64; + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vmulq_s64(a_.neon_f64, b_.neon_f64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] * b_.i64[i]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_mod_epi64 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 % b_.i64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] % b_.i64[i]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_mul_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_mul_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 * b_.f64; + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vmulq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_mul(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] * b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mul_pd(a, b) simde_mm_mul_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_mul_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_mul_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_mul_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x2_t temp = vmulq_f64(a_.neon_f64, b_.neon_f64); + r_.neon_f64 = vsetq_lane_f64(vgetq_lane(a_.neon_f64, 1), temp, 1); + #else + r_.f64[0] = a_.f64[0] * b_.f64[0]; + r_.f64[1] = a_.f64[1]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mul_sd(a, b) simde_mm_mul_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_mul_su32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) && !defined(__PGI) + return _mm_mul_su32(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.u64[0] = vget_lane_u64(vget_low_u64(vmull_u32(vreinterpret_u32_s64(a_.neon_i64), vreinterpret_u32_s64(b_.neon_i64))), 0); + #else + r_.u64[0] = HEDLEY_STATIC_CAST(uint64_t, a_.u32[0]) * HEDLEY_STATIC_CAST(uint64_t, b_.u32[0]); + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mul_su32(a, b) simde_mm_mul_su32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mulhi_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_mulhi_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4_t a3210 = vget_low_s16(a_.neon_i16); + int16x4_t b3210 = vget_low_s16(b_.neon_i16); + int32x4_t ab3210 = vmull_s16(a3210, b3210); /* 3333222211110000 */ + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + int32x4_t ab7654 = vmull_high_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = vuzp2q_s16(vreinterpretq_s16_s32(ab3210), vreinterpretq_s16_s32(ab7654)); + #else + int16x4_t a7654 = vget_high_s16(a_.neon_i16); + int16x4_t b7654 = vget_high_s16(b_.neon_i16); + int32x4_t ab7654 = vmull_s16(a7654, b7654); /* 7777666655554444 */ + uint16x8x2_t rv = vuzpq_u16(vreinterpretq_u16_s32(ab3210), vreinterpretq_u16_s32(ab7654)); + r_.neon_u16 = rv.val[1]; + #endif + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, (HEDLEY_STATIC_CAST(uint32_t, HEDLEY_STATIC_CAST(int32_t, a_.i16[i]) * HEDLEY_STATIC_CAST(int32_t, b_.i16[i])) >> 16)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mulhi_epi16(a, b) simde_mm_mulhi_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mulhi_epu16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + return _mm_mulhi_epu16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint16x4_t a3210 = vget_low_u16(a_.neon_u16); + uint16x4_t b3210 = vget_low_u16(b_.neon_u16); + uint32x4_t ab3210 = vmull_u16(a3210, b3210); /* 3333222211110000 */ + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint32x4_t ab7654 = vmull_high_u16(a_.neon_u16, b_.neon_u16); + r_.neon_u16 = vuzp2q_u16(vreinterpretq_u16_u32(ab3210), vreinterpretq_u16_u32(ab7654)); + #else + uint16x4_t a7654 = vget_high_u16(a_.neon_u16); + uint16x4_t b7654 = vget_high_u16(b_.neon_u16); + uint32x4_t ab7654 = vmull_u16(a7654, b7654); /* 7777666655554444 */ + uint16x8x2_t neon_r = vuzpq_u16(vreinterpretq_u16_u32(ab3210), vreinterpretq_u16_u32(ab7654)); + r_.neon_u16 = neon_r.val[1]; + #endif + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, HEDLEY_STATIC_CAST(uint32_t, a_.u16[i]) * HEDLEY_STATIC_CAST(uint32_t, b_.u16[i]) >> 16); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mulhi_epu16(a, b) simde_mm_mulhi_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mullo_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_mullo_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vmulq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + (void) a_; + (void) b_; + r_.altivec_i16 = vec_mul(a_.altivec_i16, b_.altivec_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, HEDLEY_STATIC_CAST(uint32_t, a_.u16[i]) * HEDLEY_STATIC_CAST(uint32_t, b_.u16[i])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mullo_epi16(a, b) simde_mm_mullo_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_or_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_or_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f | b_.i32f; + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_or(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vorrq_s64(a_.neon_i64, b_.neon_i64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] | b_.i32f[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_or_pd(a, b) simde_mm_or_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_or_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_or_si128(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vorrq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_or(a_.altivec_i32, b_.altivec_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f | b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] | b_.i32f[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_or_si128(a, b) simde_mm_or_si128(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_packs_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_packs_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vcombine_s8(vqmovn_s16(a_.neon_i16), vqmovn_s16(b_.neon_i16)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i8[i] = (a_.i16[i] > INT8_MAX) ? INT8_MAX : ((a_.i16[i] < INT8_MIN) ? INT8_MIN : HEDLEY_STATIC_CAST(int8_t, a_.i16[i])); + r_.i8[i + 8] = (b_.i16[i] > INT8_MAX) ? INT8_MAX : ((b_.i16[i] < INT8_MIN) ? INT8_MIN : HEDLEY_STATIC_CAST(int8_t, b_.i16[i])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_packs_epi16(a, b) simde_mm_packs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_packs_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_packs_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vcombine_s16(vqmovn_s32(a_.neon_i32), vqmovn_s32(b_.neon_i32)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i16 = vec_packs(a_.altivec_i32, b_.altivec_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i16[i] = (a_.i32[i] > INT16_MAX) ? INT16_MAX : ((a_.i32[i] < INT16_MIN) ? INT16_MIN : HEDLEY_STATIC_CAST(int16_t, a_.i32[i])); + r_.i16[i + 4] = (b_.i32[i] > INT16_MAX) ? INT16_MAX : ((b_.i32[i] < INT16_MIN) ? INT16_MIN : HEDLEY_STATIC_CAST(int16_t, b_.i32[i])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_packs_epi32(a, b) simde_mm_packs_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_packus_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_packus_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vcombine_u8(vqmovun_s16(a_.neon_i16), vqmovun_s16(b_.neon_i16)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_u8 = vec_packsu(a_.altivec_i16, b_.altivec_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u8[i] = (a_.i16[i] > UINT8_MAX) ? UINT8_MAX : ((a_.i16[i] < 0) ? UINT8_C(0) : HEDLEY_STATIC_CAST(uint8_t, a_.i16[i])); + r_.u8[i + 8] = (b_.i16[i] > UINT8_MAX) ? UINT8_MAX : ((b_.i16[i] < 0) ? UINT8_C(0) : HEDLEY_STATIC_CAST(uint8_t, b_.i16[i])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_packus_epi16(a, b) simde_mm_packus_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_pause (void) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_pause(); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_pause() (simde_mm_pause()) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sad_epu8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sad_epu8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const uint16x8_t t = vpaddlq_u8(vabdq_u8(a_.neon_u8, b_.neon_u8)); + r_.neon_u64 = vcombine_u64( + vpaddl_u32(vpaddl_u16(vget_low_u16(t))), + vpaddl_u32(vpaddl_u16(vget_high_u16(t)))); + #else + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + uint16_t tmp = 0; + SIMDE_VECTORIZE_REDUCTION(+:tmp) + for (size_t j = 0 ; j < ((sizeof(r_.u8) / sizeof(r_.u8[0])) / 2) ; j++) { + const size_t e = j + (i * 8); + tmp += (a_.u8[e] > b_.u8[e]) ? (a_.u8[e] - b_.u8[e]) : (b_.u8[e] - a_.u8[e]); + } + r_.i64[i] = tmp; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sad_epu8(a, b) simde_mm_sad_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set_epi8 (int8_t e15, int8_t e14, int8_t e13, int8_t e12, + int8_t e11, int8_t e10, int8_t e9, int8_t e8, + int8_t e7, int8_t e6, int8_t e5, int8_t e4, + int8_t e3, int8_t e2, int8_t e1, int8_t e0) { + + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_epi8( + e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m128i_private r_; + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_make( + e0, e1, e2, e3, e4, e5, e6, e7, + e8, e9, e10, e11, e12, e13, e14, e15); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(int8x16_t) int8_t data[16] = { + e0, e1, e2, e3, + e4, e5, e6, e7, + e8, e9, e10, e11, + e12, e13, e14, e15}; + r_.neon_i8 = vld1q_s8(data); + #else + r_.i8[ 0] = e0; + r_.i8[ 1] = e1; + r_.i8[ 2] = e2; + r_.i8[ 3] = e3; + r_.i8[ 4] = e4; + r_.i8[ 5] = e5; + r_.i8[ 6] = e6; + r_.i8[ 7] = e7; + r_.i8[ 8] = e8; + r_.i8[ 9] = e9; + r_.i8[10] = e10; + r_.i8[11] = e11; + r_.i8[12] = e12; + r_.i8[13] = e13; + r_.i8[14] = e14; + r_.i8[15] = e15; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_epi8(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) simde_mm_set_epi8(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set_epi16 (int16_t e7, int16_t e6, int16_t e5, int16_t e4, + int16_t e3, int16_t e2, int16_t e1, int16_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_epi16(e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(int16x8_t) int16_t data[8] = { e0, e1, e2, e3, e4, e5, e6, e7 }; + r_.neon_i16 = vld1q_s16(data); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_make(e0, e1, e2, e3, e4, e5, e6, e7); + #else + r_.i16[0] = e0; + r_.i16[1] = e1; + r_.i16[2] = e2; + r_.i16[3] = e3; + r_.i16[4] = e4; + r_.i16[5] = e5; + r_.i16[6] = e6; + r_.i16[7] = e7; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_epi16(e7, e6, e5, e4, e3, e2, e1, e0) simde_mm_set_epi16(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_si16 (void const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(8,0,0) || \ + HEDLEY_GCC_VERSION_CHECK(11,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(20,21,1)) + return _mm_loadu_si16(mem_addr); + #else + int16_t val; + simde_memcpy(&val, mem_addr, sizeof(val)); + return simde_x_mm_cvtsi16_si128(val); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadu_si16(mem_addr) simde_mm_loadu_si16(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set_epi32 (int32_t e3, int32_t e2, int32_t e1, int32_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_epi32(e3, e2, e1, e0); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(int32x4_t) int32_t data[4] = { e0, e1, e2, e3 }; + r_.neon_i32 = vld1q_s32(data); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_make(e0, e1, e2, e3); + #else + r_.i32[0] = e0; + r_.i32[1] = e1; + r_.i32[2] = e2; + r_.i32[3] = e3; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_epi32(e3, e2, e1, e0) simde_mm_set_epi32(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_si32 (void const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(8,0,0) || \ + HEDLEY_GCC_VERSION_CHECK(11,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(20,21,1)) + return _mm_loadu_si32(mem_addr); + #else + int32_t val; + simde_memcpy(&val, mem_addr, sizeof(val)); + return simde_mm_cvtsi32_si128(val); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadu_si32(mem_addr) simde_mm_loadu_si32(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set_epi64 (simde__m64 e1, simde__m64 e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_set_epi64(e1, e0); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vcombine_s64(simde__m64_to_neon_i64(e0), simde__m64_to_neon_i64(e1)); + #else + r_.m64[0] = e0; + r_.m64[1] = e1; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_epi64(e1, e0) (simde_mm_set_epi64((e1), (e0))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set_epi64x (int64_t e1, int64_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) && (!defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19,0,0)) + return _mm_set_epi64x(e1, e0); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(int64x2_t) int64_t data[2] = {e0, e1}; + r_.neon_i64 = vld1q_s64(data); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i64x2_make(e0, e1); + #else + r_.i64[0] = e0; + r_.i64[1] = e1; + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_epi64x(e1, e0) simde_mm_set_epi64x(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_loadu_si64 (void const* mem_addr) { + #if defined(SIMDE_X86_SSE2_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(8,0,0) || \ + HEDLEY_GCC_VERSION_CHECK(11,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(20,21,1)) + return _mm_loadu_si64(mem_addr); + #else + int64_t val; + simde_memcpy(&val, mem_addr, sizeof(val)); + return simde_mm_cvtsi64_si128(val); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_loadu_si64(mem_addr) simde_mm_loadu_si64(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set_epu8 (uint8_t e15, uint8_t e14, uint8_t e13, uint8_t e12, + uint8_t e11, uint8_t e10, uint8_t e9, uint8_t e8, + uint8_t e7, uint8_t e6, uint8_t e5, uint8_t e4, + uint8_t e3, uint8_t e2, uint8_t e1, uint8_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_epi8( + HEDLEY_STATIC_CAST(char, e15), HEDLEY_STATIC_CAST(char, e14), HEDLEY_STATIC_CAST(char, e13), HEDLEY_STATIC_CAST(char, e12), + HEDLEY_STATIC_CAST(char, e11), HEDLEY_STATIC_CAST(char, e10), HEDLEY_STATIC_CAST(char, e9), HEDLEY_STATIC_CAST(char, e8), + HEDLEY_STATIC_CAST(char, e7), HEDLEY_STATIC_CAST(char, e6), HEDLEY_STATIC_CAST(char, e5), HEDLEY_STATIC_CAST(char, e4), + HEDLEY_STATIC_CAST(char, e3), HEDLEY_STATIC_CAST(char, e2), HEDLEY_STATIC_CAST(char, e1), HEDLEY_STATIC_CAST(char, e0)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(uint8x16_t) uint8_t data[16] = { + e0, e1, e2, e3, + e4, e5, e6, e7, + e8, e9, e10, e11, + e12, e13, e14, e15}; + r_.neon_u8 = vld1q_u8(data); + #else + r_.u8[ 0] = e0; r_.u8[ 1] = e1; r_.u8[ 2] = e2; r_.u8[ 3] = e3; + r_.u8[ 4] = e4; r_.u8[ 5] = e5; r_.u8[ 6] = e6; r_.u8[ 7] = e7; + r_.u8[ 8] = e8; r_.u8[ 9] = e9; r_.u8[10] = e10; r_.u8[11] = e11; + r_.u8[12] = e12; r_.u8[13] = e13; r_.u8[14] = e14; r_.u8[15] = e15; + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set_epu16 (uint16_t e7, uint16_t e6, uint16_t e5, uint16_t e4, + uint16_t e3, uint16_t e2, uint16_t e1, uint16_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_epi16( + HEDLEY_STATIC_CAST(short, e7), HEDLEY_STATIC_CAST(short, e6), HEDLEY_STATIC_CAST(short, e5), HEDLEY_STATIC_CAST(short, e4), + HEDLEY_STATIC_CAST(short, e3), HEDLEY_STATIC_CAST(short, e2), HEDLEY_STATIC_CAST(short, e1), HEDLEY_STATIC_CAST(short, e0)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(uint16x8_t) uint16_t data[8] = { e0, e1, e2, e3, e4, e5, e6, e7 }; + r_.neon_u16 = vld1q_u16(data); + #else + r_.u16[0] = e0; r_.u16[1] = e1; r_.u16[2] = e2; r_.u16[3] = e3; + r_.u16[4] = e4; r_.u16[5] = e5; r_.u16[6] = e6; r_.u16[7] = e7; + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set_epu32 (uint32_t e3, uint32_t e2, uint32_t e1, uint32_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_epi32( + HEDLEY_STATIC_CAST(int, e3), HEDLEY_STATIC_CAST(int, e2), HEDLEY_STATIC_CAST(int, e1), HEDLEY_STATIC_CAST(int, e0)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(uint32x4_t) uint32_t data[4] = { e0, e1, e2, e3 }; + r_.neon_u32 = vld1q_u32(data); + #else + r_.u32[0] = e0; + r_.u32[1] = e1; + r_.u32[2] = e2; + r_.u32[3] = e3; + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set_epu64x (uint64_t e1, uint64_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) && (!defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19,0,0)) + return _mm_set_epi64x(HEDLEY_STATIC_CAST(int64_t, e1), HEDLEY_STATIC_CAST(int64_t, e0)); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + SIMDE_ALIGN_LIKE_16(uint64x2_t) uint64_t data[2] = {e0, e1}; + r_.neon_u64 = vld1q_u64(data); + #else + r_.u64[0] = e0; + r_.u64[1] = e1; + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_set_sd (simde_float64 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set_sd(a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return vsetq_lane_f64(a, vdupq_n_f64(SIMDE_FLOAT64_C(0.0)), 0); + #else + return simde_mm_set_pd(SIMDE_FLOAT64_C(0.0), a); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set_sd(a) simde_mm_set_sd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set1_epi8 (int8_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set1_epi8(a); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vdupq_n_s8(a); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_splat(a); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_splats(HEDLEY_STATIC_CAST(signed char, a)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set1_epi8(a) simde_mm_set1_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set1_epi16 (int16_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set1_epi16(a); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vdupq_n_s16(a); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_splat(a); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = vec_splats(HEDLEY_STATIC_CAST(signed short, a)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set1_epi16(a) simde_mm_set1_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set1_epi32 (int32_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_set1_epi32(a); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vdupq_n_s32(a); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_splat(a); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_splats(HEDLEY_STATIC_CAST(signed int, a)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set1_epi32(a) simde_mm_set1_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set1_epi64x (int64_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && (!defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19,0,0)) + return _mm_set1_epi64x(a); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vdupq_n_s64(a); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i64x2_splat(a); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i64 = vec_splats(HEDLEY_STATIC_CAST(signed long long, a)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set1_epi64x(a) simde_mm_set1_epi64x(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_set1_epi64 (simde__m64 a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_set1_epi64(a); + #else + simde__m64_private a_ = simde__m64_to_private(a); + return simde_mm_set1_epi64x(a_.i64[0]); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_set1_epi64(a) simde_mm_set1_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set1_epu8 (uint8_t value) { + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + return simde__m128i_from_altivec_u8(vec_splats(HEDLEY_STATIC_CAST(unsigned char, value))); + #else + return simde_mm_set1_epi8(HEDLEY_STATIC_CAST(int8_t, value)); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set1_epu16 (uint16_t value) { + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + return simde__m128i_from_altivec_u16(vec_splats(HEDLEY_STATIC_CAST(unsigned short, value))); + #else + return simde_mm_set1_epi16(HEDLEY_STATIC_CAST(int16_t, value)); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set1_epu32 (uint32_t value) { + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + return simde__m128i_from_altivec_u32(vec_splats(HEDLEY_STATIC_CAST(unsigned int, value))); + #else + return simde_mm_set1_epi32(HEDLEY_STATIC_CAST(int32_t, value)); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_set1_epu64 (uint64_t value) { + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + return simde__m128i_from_altivec_u64(vec_splats(HEDLEY_STATIC_CAST(unsigned long long, value))); + #else + return simde_mm_set1_epi64x(HEDLEY_STATIC_CAST(int64_t, value)); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_setr_epi8 (int8_t e15, int8_t e14, int8_t e13, int8_t e12, + int8_t e11, int8_t e10, int8_t e9, int8_t e8, + int8_t e7, int8_t e6, int8_t e5, int8_t e4, + int8_t e3, int8_t e2, int8_t e1, int8_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_setr_epi8( + e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm_set_epi8( + e0, e1, e2, e3, e4, e5, e6, e7, + e8, e9, e10, e11, e12, e13, e14, e15); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setr_epi8(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) simde_mm_setr_epi8(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_setr_epi16 (int16_t e7, int16_t e6, int16_t e5, int16_t e4, + int16_t e3, int16_t e2, int16_t e1, int16_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_setr_epi16(e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm_set_epi16(e0, e1, e2, e3, e4, e5, e6, e7); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setr_epi16(e7, e6, e5, e4, e3, e2, e1, e0) simde_mm_setr_epi16(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_setr_epi32 (int32_t e3, int32_t e2, int32_t e1, int32_t e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_setr_epi32(e3, e2, e1, e0); + #else + return simde_mm_set_epi32(e0, e1, e2, e3); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setr_epi32(e3, e2, e1, e0) simde_mm_setr_epi32(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_setr_epi64 (simde__m64 e1, simde__m64 e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_setr_epi64(e1, e0); + #else + return simde_mm_set_epi64(e0, e1); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setr_epi64(e1, e0) (simde_mm_setr_epi64((e1), (e0))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_setr_pd (simde_float64 e1, simde_float64 e0) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_setr_pd(e1, e0); + #else + return simde_mm_set_pd(e0, e1); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setr_pd(e1, e0) simde_mm_setr_pd(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_setzero_pd (void) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_setzero_pd(); + #else + return simde_mm_castsi128_pd(simde_mm_setzero_si128()); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_setzero_pd() simde_mm_setzero_pd() +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_undefined_pd (void) { + simde__m128d_private r_; + + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE__HAVE_UNDEFINED128) + r_.n = _mm_undefined_pd(); + #elif !defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + r_ = simde__m128d_to_private(simde_mm_setzero_pd()); + #endif + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_undefined_pd() simde_mm_undefined_pd() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_undefined_si128 (void) { + simde__m128i_private r_; + + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE__HAVE_UNDEFINED128) + r_.n = _mm_undefined_si128(); + #elif !defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_undefined_si128() (simde_mm_undefined_si128()) +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) +HEDLEY_DIAGNOSTIC_POP +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_setone_pd (void) { + return simde_mm_castps_pd(simde_x_mm_setone_ps()); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_setone_si128 (void) { + return simde_mm_castps_si128(simde_x_mm_setone_ps()); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_shuffle_epi32 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[(imm8 >> (i * 2)) & 3]; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_shuffle_epi32(a, imm8) _mm_shuffle_epi32((a), (imm8)) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_shuffle_epi32(a, imm8) \ + __extension__({ \ + int32x4_t ret; \ + ret = vmovq_n_s32( \ + vgetq_lane_s32(vreinterpretq_s32_s64(a), (imm8) & (0x3))); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_s64(a), ((imm8) >> 2) & 0x3), \ + ret, 1); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_s64(a), ((imm8) >> 4) & 0x3), \ + ret, 2); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_s64(a), ((imm8) >> 6) & 0x3), \ + ret, 3); \ + vreinterpretq_s64_s32(ret); \ + }) +#elif defined(SIMDE_SHUFFLE_VECTOR_) + #define simde_mm_shuffle_epi32(a, imm8) (__extension__ ({ \ + const simde__m128i_private simde__tmp_a_ = simde__m128i_to_private(a); \ + simde__m128i_from_private((simde__m128i_private) { .i32 = \ + SIMDE_SHUFFLE_VECTOR_(32, 16, \ + (simde__tmp_a_).i32, \ + (simde__tmp_a_).i32, \ + ((imm8) ) & 3, \ + ((imm8) >> 2) & 3, \ + ((imm8) >> 4) & 3, \ + ((imm8) >> 6) & 3) }); })) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_shuffle_epi32(a, imm8) simde_mm_shuffle_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_shuffle_pd (simde__m128d a, simde__m128d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.f64[0] = ((imm8 & 1) == 0) ? a_.f64[0] : a_.f64[1]; + r_.f64[1] = ((imm8 & 2) == 0) ? b_.f64[0] : b_.f64[1]; + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) && !defined(__PGI) + #define simde_mm_shuffle_pd(a, b, imm8) _mm_shuffle_pd((a), (b), (imm8)) +#elif defined(SIMDE_SHUFFLE_VECTOR_) + #define simde_mm_shuffle_pd(a, b, imm8) (__extension__ ({ \ + simde__m128d_from_private((simde__m128d_private) { .f64 = \ + SIMDE_SHUFFLE_VECTOR_(64, 16, \ + simde__m128d_to_private(a).f64, \ + simde__m128d_to_private(b).f64, \ + (((imm8) ) & 1), \ + (((imm8) >> 1) & 1) + 2) }); })) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_shuffle_pd(a, b, imm8) simde_mm_shuffle_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_shufflehi_epi16 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(a_.i16) / sizeof(a_.i16[0])) / 2) ; i++) { + r_.i16[i] = a_.i16[i]; + } + for (size_t i = ((sizeof(a_.i16) / sizeof(a_.i16[0])) / 2) ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[((imm8 >> ((i - 4) * 2)) & 3) + 4]; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_shufflehi_epi16(a, imm8) _mm_shufflehi_epi16((a), (imm8)) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_shufflehi_epi16(a, imm8) \ + __extension__({ \ + int16x8_t ret = vreinterpretq_s16_s64(a); \ + int16x4_t highBits = vget_high_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm8) & (0x3)), ret, 4); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm8) >> 2) & 0x3), ret, \ + 5); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm8) >> 4) & 0x3), ret, \ + 6); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm8) >> 6) & 0x3), ret, \ + 7); \ + vreinterpretq_s64_s16(ret); \ + }) +#elif defined(SIMDE_SHUFFLE_VECTOR_) + #define simde_mm_shufflehi_epi16(a, imm8) (__extension__ ({ \ + const simde__m128i_private simde__tmp_a_ = simde__m128i_to_private(a); \ + simde__m128i_from_private((simde__m128i_private) { .i16 = \ + SIMDE_SHUFFLE_VECTOR_(16, 16, \ + (simde__tmp_a_).i16, \ + (simde__tmp_a_).i16, \ + 0, 1, 2, 3, \ + (((imm8) ) & 3) + 4, \ + (((imm8) >> 2) & 3) + 4, \ + (((imm8) >> 4) & 3) + 4, \ + (((imm8) >> 6) & 3) + 4) }); })) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_shufflehi_epi16(a, imm8) simde_mm_shufflehi_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_shufflelo_epi16 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + for (size_t i = 0 ; i < ((sizeof(r_.i16) / sizeof(r_.i16[0])) / 2) ; i++) { + r_.i16[i] = a_.i16[((imm8 >> (i * 2)) & 3)]; + } + SIMDE_VECTORIZE + for (size_t i = ((sizeof(a_.i16) / sizeof(a_.i16[0])) / 2) ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i]; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_shufflelo_epi16(a, imm8) _mm_shufflelo_epi16((a), (imm8)) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_shufflelo_epi16(a, imm8) \ + __extension__({ \ + int16x8_t ret = vreinterpretq_s16_s64(a); \ + int16x4_t lowBits = vget_low_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm8) & (0x3)), ret, 0); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm8) >> 2) & 0x3), ret, \ + 1); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm8) >> 4) & 0x3), ret, \ + 2); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm8) >> 6) & 0x3), ret, \ + 3); \ + vreinterpretq_s64_s16(ret); \ + }) +#elif defined(SIMDE_SHUFFLE_VECTOR_) + #define simde_mm_shufflelo_epi16(a, imm8) (__extension__ ({ \ + const simde__m128i_private simde__tmp_a_ = simde__m128i_to_private(a); \ + simde__m128i_from_private((simde__m128i_private) { .i16 = \ + SIMDE_SHUFFLE_VECTOR_(16, 16, \ + (simde__tmp_a_).i16, \ + (simde__tmp_a_).i16, \ + (((imm8) ) & 3), \ + (((imm8) >> 2) & 3), \ + (((imm8) >> 4) & 3), \ + (((imm8) >> 6) & 3), \ + 4, 5, 6, 7) }); })) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_shufflelo_epi16(a, imm8) simde_mm_shufflelo_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sll_epi16 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sll_epi16(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + if (count_.u64[0] > 15) + return simde_mm_setzero_si128(); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u16 = (a_.u16 << count_.u64[0]); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vshlq_u16(a_.neon_u16, vdupq_n_s16(HEDLEY_STATIC_CAST(int16_t, count_.u64[0]))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = ((wasm_i64x2_extract_lane(count_.wasm_v128, 0) < 16) ? wasm_i16x8_shl(a_.wasm_v128, HEDLEY_STATIC_CAST(int32_t, wasm_i64x2_extract_lane(count_.wasm_v128, 0))) : wasm_i16x8_const(0,0,0,0,0,0,0,0)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, (a_.u16[i] << count_.u64[0])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sll_epi16(a, count) simde_mm_sll_epi16((a), (count)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sll_epi32 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sll_epi32(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + if (count_.u64[0] > 31) + return simde_mm_setzero_si128(); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = (a_.u32 << count_.u64[0]); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vshlq_u32(a_.neon_u32, vdupq_n_s32(HEDLEY_STATIC_CAST(int32_t, count_.u64[0]))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = ((wasm_i64x2_extract_lane(count_.wasm_v128, 0) < 32) ? wasm_i32x4_shl(a_.wasm_v128, HEDLEY_STATIC_CAST(int32_t, wasm_i64x2_extract_lane(count_.wasm_v128, 0))) : wasm_i32x4_const(0,0,0,0)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = HEDLEY_STATIC_CAST(uint32_t, (a_.u32[i] << count_.u64[0])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sll_epi32(a, count) (simde_mm_sll_epi32(a, (count))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sll_epi64 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sll_epi64(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + if (count_.u64[0] > 63) + return simde_mm_setzero_si128(); + + const int_fast16_t s = HEDLEY_STATIC_CAST(int_fast16_t, count_.u64[0]); + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u64 = vshlq_u64(a_.neon_u64, vdupq_n_s64(HEDLEY_STATIC_CAST(int64_t, s))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = (s < 64) ? wasm_i64x2_shl(a_.wasm_v128, s) : wasm_i64x2_const(0,0); + #else + #if !defined(SIMDE_BUG_GCC_94488) + SIMDE_VECTORIZE + #endif + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = a_.u64[i] << s; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sll_epi64(a, count) (simde_mm_sll_epi64(a, (count))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_sqrt_pd (simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sqrt_pd(a); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vsqrtq_f64(a_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_sqrt(a_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = vec_sqrt(a_.altivec_f64); + #elif defined(simde_math_sqrt) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_sqrt(a_.f64[i]); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sqrt_pd(a) simde_mm_sqrt_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_sqrt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sqrt_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_sqrt_pd(b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(simde_math_sqrt) + r_.f64[0] = simde_math_sqrt(b_.f64[0]); + r_.f64[1] = a_.f64[1]; + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sqrt_sd(a, b) simde_mm_sqrt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srl_epi16 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_srl_epi16(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + const int cnt = HEDLEY_STATIC_CAST(int, (count_.i64[0] > 16 ? 16 : count_.i64[0])); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vshlq_u16(a_.neon_u16, vdupq_n_s16(HEDLEY_STATIC_CAST(int16_t, -cnt))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = a_.u16[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srl_epi16(a, count) (simde_mm_srl_epi16(a, (count))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srl_epi32 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_srl_epi32(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + const int cnt = HEDLEY_STATIC_CAST(int, (count_.i64[0] > 32 ? 32 : count_.i64[0])); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vshlq_u32(a_.neon_u32, vdupq_n_s32(HEDLEY_STATIC_CAST(int32_t, -cnt))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u32x4_shr(a_.wasm_v128, cnt); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srl_epi32(a, count) (simde_mm_srl_epi32(a, (count))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srl_epi64 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_srl_epi64(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + const int cnt = HEDLEY_STATIC_CAST(int, (count_.i64[0] > 64 ? 64 : count_.i64[0])); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u64 = vshlq_u64(a_.neon_u64, vdupq_n_s64(HEDLEY_STATIC_CAST(int64_t, -cnt))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u64x2_shr(a_.wasm_v128, cnt); + #else + #if !defined(SIMDE_BUG_GCC_94488) + SIMDE_VECTORIZE + #endif + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = a_.u64[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srl_epi64(a, count) (simde_mm_srl_epi64(a, (count))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srai_epi16 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + /* MSVC requires a range of (0, 255). */ + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + const int cnt = (imm8 & ~15) ? 15 : imm8; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vshlq_s16(a_.neon_i16, vdupq_n_s16(HEDLEY_STATIC_CAST(int16_t, -cnt))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_shr(a_.wasm_v128, cnt); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_srai_epi16(a, imm8) _mm_srai_epi16((a), (imm8)) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srai_epi16(a, imm8) simde_mm_srai_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srai_epi32 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + /* MSVC requires a range of (0, 255). */ + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + const int cnt = (imm8 & ~31) ? 31 : imm8; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vshlq_s32(a_.neon_i32, vdupq_n_s32(-cnt)); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_shr(a_.wasm_v128, cnt); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_srai_epi32(a, imm8) _mm_srai_epi32((a), (imm8)) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srai_epi32(a, imm8) simde_mm_srai_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sra_epi16 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sra_epi16(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + const int cnt = HEDLEY_STATIC_CAST(int, (count_.i64[0] > 15 ? 15 : count_.i64[0])); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vshlq_s16(a_.neon_i16, vdupq_n_s16(HEDLEY_STATIC_CAST(int16_t, -cnt))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_shr(a_.wasm_v128, cnt); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sra_epi16(a, count) (simde_mm_sra_epi16(a, count)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sra_epi32 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_SSE2_NATIVE) && !defined(SIMDE_BUG_GCC_BAD_MM_SRA_EPI32) + return _mm_sra_epi32(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + const int cnt = count_.u64[0] > 31 ? 31 : HEDLEY_STATIC_CAST(int, count_.u64[0]); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vshlq_s32(a_.neon_i32, vdupq_n_s32(HEDLEY_STATIC_CAST(int32_t, -cnt))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_shr(a_.wasm_v128, cnt); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] >> cnt; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sra_epi32(a, count) (simde_mm_sra_epi32(a, (count))) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_slli_epi16 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + if (HEDLEY_UNLIKELY((imm8 > 15))) { + return simde_mm_setzero_si128(); + } + + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 << SIMDE_CAST_VECTOR_SHIFT_COUNT(8, imm8 & 0xff); + #else + const int s = (imm8 > HEDLEY_STATIC_CAST(int, sizeof(r_.i16[0]) * CHAR_BIT) - 1) ? 0 : imm8; + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, a_.i16[i] << s); + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_slli_epi16(a, imm8) _mm_slli_epi16(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_slli_epi16(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 15) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_neon_i16( \ + vshlq_n_s16(simde__m128i_to_neon_i16(a), ((imm8) & 15))); \ + } \ + ret; \ + })) +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + #define simde_mm_slli_epi16(a, imm8) \ + ((imm8 < 16) ? wasm_i16x8_shl(simde__m128i_to_private(a).wasm_v128, imm8) : wasm_i16x8_const(0,0,0,0,0,0,0,0)) +#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + #define simde_mm_slli_epi16(a, imm8) \ + ((imm8 & ~15) ? simde_mm_setzero_si128() : simde__m128i_from_altivec_i16(vec_sl(simde__m128i_to_altivec_i16(a), vec_splat_u16(HEDLEY_STATIC_CAST(unsigned short, imm8))))) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_slli_epi16(a, imm8) simde_mm_slli_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_slli_epi32 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + if (HEDLEY_UNLIKELY((imm8 > 31))) { + return simde_mm_setzero_si128(); + } + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 << imm8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] << (imm8 & 0xff); + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_slli_epi32(a, imm8) _mm_slli_epi32(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_slli_epi32(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 31) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_neon_i32( \ + vshlq_n_s32(simde__m128i_to_neon_i32(a), ((imm8) & 31))); \ + } \ + ret; \ + })) +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + #define simde_mm_slli_epi32(a, imm8) \ + ((imm8 < 32) ? wasm_i32x4_shl(simde__m128i_to_private(a).wasm_v128, imm8) : wasm_i32x4_const(0,0,0,0)) +#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + #define simde_mm_slli_epi32(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 31) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_altivec_i32( \ + vec_sl(simde__m128i_to_altivec_i32(a), \ + vec_splats(HEDLEY_STATIC_CAST(unsigned int, (imm8) & 31)))); \ + } \ + ret; \ + })) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_slli_epi32(a, imm8) simde_mm_slli_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_slli_epi64 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + if (HEDLEY_UNLIKELY((imm8 > 63))) { + return simde_mm_setzero_si128(); + } + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i64 = a_.i64 << imm8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] << (imm8 & 0xff); + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_slli_epi64(a, imm8) _mm_slli_epi64(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_slli_epi64(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 63) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_neon_i64( \ + vshlq_n_s64(simde__m128i_to_neon_i64(a), ((imm8) & 63))); \ + } \ + ret; \ + })) +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + #define simde_mm_slli_epi64(a, imm8) \ + ((imm8 < 64) ? wasm_i64x2_shl(simde__m128i_to_private(a).wasm_v128, imm8) : wasm_i64x2_const(0,0)) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_slli_epi64(a, imm8) simde_mm_slli_epi64(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srli_epi16 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + if (HEDLEY_UNLIKELY((imm8 > 15))) { + return simde_mm_setzero_si128(); + } + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u16 = a_.u16 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(8, imm8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = a_.u16[i] >> (imm8 & 0xff); + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_srli_epi16(a, imm8) _mm_srli_epi16(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_srli_epi16(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 15) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_neon_u16( \ + vshrq_n_u16(simde__m128i_to_neon_u16(a), (((imm8) & 15) | (((imm8) & 15) == 0)))); \ + } \ + ret; \ + })) +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + #define simde_mm_srli_epi16(a, imm8) \ + ((imm8 < 16) ? wasm_u16x8_shr(simde__m128i_to_private(a).wasm_v128, imm8) : wasm_i16x8_const(0,0,0,0,0,0,0,0)) +#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + #define simde_mm_srli_epi16(a, imm8) \ + ((imm8 & ~15) ? simde_mm_setzero_si128() : simde__m128i_from_altivec_i16(vec_sr(simde__m128i_to_altivec_i16(a), vec_splat_u16(HEDLEY_STATIC_CAST(unsigned short, imm8))))) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srli_epi16(a, imm8) simde_mm_srli_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srli_epi32 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + if (HEDLEY_UNLIKELY((imm8 > 31))) { + return simde_mm_setzero_si128(); + } + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = a_.u32 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(8, imm8 & 0xff); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.u32[i] = a_.u32[i] >> (imm8 & 0xff); + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_srli_epi32(a, imm8) _mm_srli_epi32(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_srli_epi32(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 31) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_neon_u32( \ + vshrq_n_u32(simde__m128i_to_neon_u32(a), (((imm8) & 31) | (((imm8) & 31) == 0)))); \ + } \ + ret; \ + })) +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + #define simde_mm_srli_epi32(a, imm8) \ + ((imm8 < 32) ? wasm_u32x4_shr(simde__m128i_to_private(a).wasm_v128, imm8) : wasm_i32x4_const(0,0,0,0)) +#elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + #define simde_mm_srli_epi32(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 31) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_altivec_i32( \ + vec_sr(simde__m128i_to_altivec_i32(a), \ + vec_splats(HEDLEY_STATIC_CAST(unsigned int, (imm8) & 31)))); \ + } \ + ret; \ + })) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srli_epi32(a, imm8) simde_mm_srli_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srli_epi64 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + if (HEDLEY_UNLIKELY((imm8 & 63) != imm8)) + return simde_mm_setzero_si128(); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u64 = vshlq_u64(a_.neon_u64, vdupq_n_s64(-imm8)); + #else + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) && !defined(SIMDE_BUG_GCC_94488) + r_.u64 = a_.u64 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(8, imm8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.u64[i] = a_.u64[i] >> imm8; + } + #endif + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE2_NATIVE) + #define simde_mm_srli_epi64(a, imm8) _mm_srli_epi64(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_srli_epi64(a, imm8) \ + (__extension__ ({ \ + simde__m128i ret; \ + if ((imm8) <= 0) { \ + ret = a; \ + } else if ((imm8) > 63) { \ + ret = simde_mm_setzero_si128(); \ + } else { \ + ret = simde__m128i_from_neon_u64( \ + vshrq_n_u64(simde__m128i_to_neon_u64(a), (((imm8) & 63) | (((imm8) & 63) == 0)))); \ + } \ + ret; \ + })) +#elif defined(SIMDE_WASM_SIMD128_NATIVE) + #define simde_mm_srli_epi64(a, imm8) \ + ((imm8 < 64) ? wasm_u64x2_shr(simde__m128i_to_private(a).wasm_v128, imm8) : wasm_i64x2_const(0,0)) +#endif +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_srli_epi64(a, imm8) simde_mm_srli_epi64(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store_pd (simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(2)], simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_store_pd(mem_addr, a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + vst1q_f64(mem_addr, simde__m128d_to_private(a).neon_f64); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_s64(HEDLEY_REINTERPRET_CAST(int64_t*, mem_addr), simde__m128d_to_private(a).neon_i64); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m128d), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_store_pd(mem_addr, a) simde_mm_store_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store1_pd (simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(2)], simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_store1_pd(mem_addr, a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + vst1q_f64(mem_addr, vdupq_laneq_f64(a_.neon_f64, 0)); + #else + mem_addr[0] = a_.f64[0]; + mem_addr[1] = a_.f64[0]; + #endif + #endif +} +#define simde_mm_store_pd1(mem_addr, a) simde_mm_store1_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_store1_pd(mem_addr, a) simde_mm_store1_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) + #define _mm_store_pd1(mem_addr, a) simde_mm_store_pd1(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store_sd (simde_float64* mem_addr, simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_store_sd(mem_addr, a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + const simde_float64 v = vgetq_lane_f64(a_.neon_f64, 0); + simde_memcpy(mem_addr, &v, sizeof(v)); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int64_t v = vgetq_lane_s64(a_.neon_i64, 0); + simde_memcpy(HEDLEY_REINTERPRET_CAST(int64_t*, mem_addr), &v, sizeof(v)); + #else + simde_float64 v = a_.f64[0]; + simde_memcpy(mem_addr, &v, sizeof(simde_float64)); + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_store_sd(mem_addr, a) simde_mm_store_sd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_store_si128 (simde__m128i* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_store_si128(HEDLEY_STATIC_CAST(__m128i*, mem_addr), a); + #else + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_s32(HEDLEY_REINTERPRET_CAST(int32_t*, mem_addr), a_.neon_i32); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m128i), &a_, sizeof(a_)); + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_store_si128(mem_addr, a) simde_mm_store_si128(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void + simde_mm_storeh_pd (simde_float64* mem_addr, simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_storeh_pd(mem_addr, a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + *mem_addr = vgetq_lane_f64(a_.neon_f64, 1); + #else + *mem_addr = a_.f64[1]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storeh_pd(mem_addr, a) simde_mm_storeh_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storel_epi64 (simde__m128i* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_storel_epi64(HEDLEY_STATIC_CAST(__m128i*, mem_addr), a); + #else + simde__m128i_private a_ = simde__m128i_to_private(a); + int64_t tmp; + + /* memcpy to prevent aliasing, tmp because we can't take the + * address of a vector element. */ + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + tmp = vgetq_lane_s64(a_.neon_i64, 0); + #elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + #endif + tmp = vec_extract(a_.altivec_i64, 0); + #else + tmp = a_.i64[0]; + #endif + + simde_memcpy(mem_addr, &tmp, sizeof(tmp)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storel_epi64(mem_addr, a) simde_mm_storel_epi64(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storel_pd (simde_float64* mem_addr, simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_storel_pd(mem_addr, a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + + simde_float64 tmp; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + tmp = vgetq_lane_f64(a_.neon_f64, 0); + #else + tmp = a_.f64[0]; + #endif + simde_memcpy(mem_addr, &tmp, sizeof(tmp)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storel_pd(mem_addr, a) simde_mm_storel_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storer_pd (simde_float64 mem_addr[2], simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_storer_pd(mem_addr, a); + #else + simde__m128d_private a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + vst1q_s64(HEDLEY_REINTERPRET_CAST(int64_t*, mem_addr), vextq_s64(a_.neon_i64, a_.neon_i64, 1)); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + a_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, a_.f64, 1, 0); + simde_mm_store_pd(mem_addr, simde__m128d_from_private(a_)); + #else + mem_addr[0] = a_.f64[1]; + mem_addr[1] = a_.f64[0]; + #endif + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storer_pd(mem_addr, a) simde_mm_storer_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeu_pd (simde_float64* mem_addr, simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_storeu_pd(mem_addr, a); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + vst1q_f64(mem_addr, simde__m128d_to_private(a).neon_f64); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storeu_pd(mem_addr, a) simde_mm_storeu_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeu_si128 (void* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_storeu_si128(HEDLEY_STATIC_CAST(__m128i*, mem_addr), a); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storeu_si128(mem_addr, a) simde_mm_storeu_si128(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeu_si16 (void* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(8,0,0) || \ + HEDLEY_GCC_VERSION_CHECK(11,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(20,21,1)) + _mm_storeu_si16(mem_addr, a); + #else + int16_t val = simde_x_mm_cvtsi128_si16(a); + simde_memcpy(mem_addr, &val, sizeof(val)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storeu_si16(mem_addr, a) simde_mm_storeu_si16(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeu_si32 (void* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(8,0,0) || \ + HEDLEY_GCC_VERSION_CHECK(11,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(20,21,1)) + _mm_storeu_si32(mem_addr, a); + #else + int32_t val = simde_mm_cvtsi128_si32(a); + simde_memcpy(mem_addr, &val, sizeof(val)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storeu_si32(mem_addr, a) simde_mm_storeu_si32(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_storeu_si64 (void* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(8,0,0) || \ + HEDLEY_GCC_VERSION_CHECK(11,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(20,21,1)) + _mm_storeu_si64(mem_addr, a); + #else + int64_t val = simde_mm_cvtsi128_si64(a); + simde_memcpy(mem_addr, &val, sizeof(val)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_storeu_si64(mem_addr, a) simde_mm_storeu_si64(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_stream_pd (simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(2)], simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_stream_pd(mem_addr, a); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_stream_pd(mem_addr, a) simde_mm_stream_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_stream_si128 (simde__m128i* mem_addr, simde__m128i a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) + _mm_stream_si128(HEDLEY_STATIC_CAST(__m128i*, mem_addr), a); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_stream_si128(mem_addr, a) simde_mm_stream_si128(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_stream_si32 (int32_t* mem_addr, int32_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_stream_si32(mem_addr, a); + #else + *mem_addr = a; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_stream_si32(mem_addr, a) simde_mm_stream_si32(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_stream_si64 (int64_t* mem_addr, int64_t a) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_ARCH_AMD64) && !defined(HEDLEY_MSVC_VERSION) + _mm_stream_si64(SIMDE_CHECKED_REINTERPRET_CAST(long long int*, int64_t*, mem_addr), a); + #else + *mem_addr = a; + #endif +} +#define simde_mm_stream_si64x(mem_addr, a) simde_mm_stream_si64(mem_addr, a) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_stream_si64(mem_addr, a) simde_mm_stream_si64(SIMDE_CHECKED_REINTERPRET_CAST(int64_t*, __int64*, mem_addr), a) + #define _mm_stream_si64x(mem_addr, a) simde_mm_stream_si64(SIMDE_CHECKED_REINTERPRET_CAST(int64_t*, __int64*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sub_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sub_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vsubq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = a_.i8 - b_.i8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] - b_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_epi8(a, b) simde_mm_sub_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sub_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sub_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vsubq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 - b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] - b_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_epi16(a, b) simde_mm_sub_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sub_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sub_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vsubq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 - b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] - b_.i32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_epi32(a, b) simde_mm_sub_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sub_epi64 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sub_epi64(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vsubq_s64(a_.neon_i64, b_.neon_i64); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 - b_.i64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] - b_.i64[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_epi64(a, b) simde_mm_sub_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_sub_epu32 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.u32 = a_.u32 - b_.u32; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vsubq_u32(a_.neon_u32, b_.neon_u32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] - b_.u32[i]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_sub_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sub_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 - b_.f64; + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vsubq_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_sub(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] - b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_pd(a, b) simde_mm_sub_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_sub_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_sub_sd(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_sd(a, simde_mm_sub_pd(a, b)); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + r_.f64[0] = a_.f64[0] - b_.f64[0]; + r_.f64[1] = a_.f64[1]; + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_sd(a, b) simde_mm_sub_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sub_si64 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSE2_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_sub_si64(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 - b_.i64; + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vsub_s64(a_.neon_i64, b_.neon_i64); + #else + r_.i64[0] = a_.i64[0] - b_.i64[0]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_sub_si64(a, b) simde_mm_sub_si64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_subs_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_subs_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vqsubq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_sub_saturate(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i8[0])) ; i++) { + if (((b_.i8[i]) > 0 && (a_.i8[i]) < INT8_MIN + (b_.i8[i]))) { + r_.i8[i] = INT8_MIN; + } else if ((b_.i8[i]) < 0 && (a_.i8[i]) > INT8_MAX + (b_.i8[i])) { + r_.i8[i] = INT8_MAX; + } else { + r_.i8[i] = (a_.i8[i]) - (b_.i8[i]); + } + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_subs_epi8(a, b) simde_mm_subs_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_subs_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_subs_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vqsubq_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_sub_saturate(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i16[0])) ; i++) { + if (((b_.i16[i]) > 0 && (a_.i16[i]) < INT16_MIN + (b_.i16[i]))) { + r_.i16[i] = INT16_MIN; + } else if ((b_.i16[i]) < 0 && (a_.i16[i]) > INT16_MAX + (b_.i16[i])) { + r_.i16[i] = INT16_MAX; + } else { + r_.i16[i] = (a_.i16[i]) - (b_.i16[i]); + } + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_subs_epi16(a, b) simde_mm_subs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_subs_epu8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_subs_epu8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u8 = vqsubq_u8(a_.neon_u8, b_.neon_u8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u8x16_sub_saturate(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_u8 = vec_subs(a_.altivec_u8, b_.altivec_u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i8[0])) ; i++) { + const int32_t x = a_.u8[i] - b_.u8[i]; + if (x < 0) { + r_.u8[i] = 0; + } else if (x > UINT8_MAX) { + r_.u8[i] = UINT8_MAX; + } else { + r_.u8[i] = HEDLEY_STATIC_CAST(uint8_t, x); + } + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_subs_epu8(a, b) simde_mm_subs_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_subs_epu16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_subs_epu16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vqsubq_u16(a_.neon_u16, b_.neon_u16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u16x8_sub_saturate(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_u16 = vec_subs(a_.altivec_u16, b_.altivec_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i16[0])) ; i++) { + const int32_t x = a_.u16[i] - b_.u16[i]; + if (x < 0) { + r_.u16[i] = 0; + } else if (x > UINT16_MAX) { + r_.u16[i] = UINT16_MAX; + } else { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, x); + } + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_subs_epu16(a, b) simde_mm_subs_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomieq_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_ucomieq_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t a_not_nan = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t b_not_nan = vceqq_f64(b_.neon_f64, b_.neon_f64); + uint64x2_t a_or_b_nan = vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(vandq_u64(a_not_nan, b_not_nan)))); + uint64x2_t a_eq_b = vceqq_f64(a_.neon_f64, b_.neon_f64); + r = !!(vgetq_lane_u64(vorrq_u64(a_or_b_nan, a_eq_b), 0) != 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) == wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f64[0] == b_.f64[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f64[0] == b_.f64[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_ucomieq_sd(a, b) simde_mm_ucomieq_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomige_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_ucomige_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t a_not_nan = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t b_not_nan = vceqq_f64(b_.neon_f64, b_.neon_f64); + uint64x2_t a_and_b_not_nan = vandq_u64(a_not_nan, b_not_nan); + uint64x2_t a_ge_b = vcgeq_f64(a_.neon_f64, b_.neon_f64); + r = !!(vgetq_lane_u64(vandq_u64(a_and_b_not_nan, a_ge_b), 0) != 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) >= wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f64[0] >= b_.f64[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f64[0] >= b_.f64[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_ucomige_sd(a, b) simde_mm_ucomige_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomigt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_ucomigt_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t a_not_nan = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t b_not_nan = vceqq_f64(b_.neon_f64, b_.neon_f64); + uint64x2_t a_and_b_not_nan = vandq_u64(a_not_nan, b_not_nan); + uint64x2_t a_gt_b = vcgtq_f64(a_.neon_f64, b_.neon_f64); + r = !!(vgetq_lane_u64(vandq_u64(a_and_b_not_nan, a_gt_b), 0) != 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) > wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f64[0] > b_.f64[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f64[0] > b_.f64[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_ucomigt_sd(a, b) simde_mm_ucomigt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomile_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_ucomile_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t a_not_nan = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t b_not_nan = vceqq_f64(b_.neon_f64, b_.neon_f64); + uint64x2_t a_or_b_nan = vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(vandq_u64(a_not_nan, b_not_nan)))); + uint64x2_t a_le_b = vcleq_f64(a_.neon_f64, b_.neon_f64); + r = !!(vgetq_lane_u64(vorrq_u64(a_or_b_nan, a_le_b), 0) != 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) <= wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f64[0] <= b_.f64[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f64[0] <= b_.f64[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_ucomile_sd(a, b) simde_mm_ucomile_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomilt_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_ucomilt_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t a_not_nan = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t b_not_nan = vceqq_f64(b_.neon_f64, b_.neon_f64); + uint64x2_t a_or_b_nan = vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(vandq_u64(a_not_nan, b_not_nan)))); + uint64x2_t a_lt_b = vcltq_f64(a_.neon_f64, b_.neon_f64); + r = !!(vgetq_lane_u64(vorrq_u64(a_or_b_nan, a_lt_b), 0) != 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) < wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f64[0] < b_.f64[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f64[0] < b_.f64[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_ucomilt_sd(a, b) simde_mm_ucomilt_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_ucomineq_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_ucomineq_sd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + int r; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + uint64x2_t a_not_nan = vceqq_f64(a_.neon_f64, a_.neon_f64); + uint64x2_t b_not_nan = vceqq_f64(b_.neon_f64, b_.neon_f64); + uint64x2_t a_and_b_not_nan = vandq_u64(a_not_nan, b_not_nan); + uint64x2_t a_neq_b = vreinterpretq_u64_u32(vmvnq_u32(vreinterpretq_u32_u64(vceqq_f64(a_.neon_f64, b_.neon_f64)))); + r = !!(vgetq_lane_u64(vandq_u64(a_and_b_not_nan, a_neq_b), 0) != 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + return wasm_f64x2_extract_lane(a_.wasm_v128, 0) != wasm_f64x2_extract_lane(b_.wasm_v128, 0); + #elif defined(SIMDE_HAVE_FENV_H) + fenv_t envp; + int x = feholdexcept(&envp); + r = a_.f64[0] != b_.f64[0]; + if (HEDLEY_LIKELY(x == 0)) + fesetenv(&envp); + #else + r = a_.f64[0] != b_.f64[0]; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_ucomineq_sd(a, b) simde_mm_ucomineq_sd(a, b) +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + HEDLEY_DIAGNOSTIC_POP +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_lfence (void) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_lfence(); + #else + simde_mm_sfence(); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_lfence() simde_mm_lfence() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_mfence (void) { + #if defined(SIMDE_X86_SSE2_NATIVE) + _mm_mfence(); + #else + simde_mm_sfence(); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_mfence() simde_mm_mfence() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpackhi_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpackhi_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i8 = vzip2q_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int8x8_t a1 = vreinterpret_s8_s16(vget_high_s16(a_.neon_i16)); + int8x8_t b1 = vreinterpret_s8_s16(vget_high_s16(b_.neon_i16)); + int8x8x2_t result = vzip_s8(a1, b1); + r_.neon_i8 = vcombine_s8(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i8 = SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, b_.i8, 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i8[0])) / 2) ; i++) { + r_.i8[(i * 2)] = a_.i8[i + ((sizeof(r_) / sizeof(r_.i8[0])) / 2)]; + r_.i8[(i * 2) + 1] = b_.i8[i + ((sizeof(r_) / sizeof(r_.i8[0])) / 2)]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpackhi_epi8(a, b) simde_mm_unpackhi_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpackhi_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpackhi_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vzip2q_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4_t a1 = vget_high_s16(a_.neon_i16); + int16x4_t b1 = vget_high_s16(b_.neon_i16); + int16x4x2_t result = vzip_s16(a1, b1); + r_.neon_i16 = vcombine_s16(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 16, a_.i16, b_.i16, 4, 12, 5, 13, 6, 14, 7, 15); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i16[0])) / 2) ; i++) { + r_.i16[(i * 2)] = a_.i16[i + ((sizeof(r_) / sizeof(r_.i16[0])) / 2)]; + r_.i16[(i * 2) + 1] = b_.i16[i + ((sizeof(r_) / sizeof(r_.i16[0])) / 2)]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpackhi_epi16(a, b) simde_mm_unpackhi_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpackhi_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpackhi_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vzip2q_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x2_t a1 = vget_high_s32(a_.neon_i32); + int32x2_t b1 = vget_high_s32(b_.neon_i32); + int32x2x2_t result = vzip_s32(a1, b1); + r_.neon_i32 = vcombine_s32(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.i32, b_.i32, 2, 6, 3, 7); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i32[0])) / 2) ; i++) { + r_.i32[(i * 2)] = a_.i32[i + ((sizeof(r_) / sizeof(r_.i32[0])) / 2)]; + r_.i32[(i * 2) + 1] = b_.i32[i + ((sizeof(r_) / sizeof(r_.i32[0])) / 2)]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpackhi_epi32(a, b) simde_mm_unpackhi_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpackhi_epi64 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpackhi_epi64(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int64x1_t a_h = vget_high_s64(a_.neon_i64); + int64x1_t b_h = vget_high_s64(b_.neon_i64); + r_.neon_i64 = vcombine_s64(a_h, b_h); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.i64, b_.i64, 1, 3); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i64[0])) / 2) ; i++) { + r_.i64[(i * 2)] = a_.i64[i + ((sizeof(r_) / sizeof(r_.i64[0])) / 2)]; + r_.i64[(i * 2) + 1] = b_.i64[i + ((sizeof(r_) / sizeof(r_.i64[0])) / 2)]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpackhi_epi64(a, b) simde_mm_unpackhi_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_unpackhi_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpackhi_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x1_t a_l = vget_high_f64(a_.f64); + float64x1_t b_l = vget_high_f64(b_.f64); + r_.neon_f64 = vcombine_f64(a_l, b_l); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v64x2_shuffle(a_.wasm_v128, b_.wasm_v128, 1, 3); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, b_.f64, 1, 3); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.f64[0])) / 2) ; i++) { + r_.f64[(i * 2)] = a_.f64[i + ((sizeof(r_) / sizeof(r_.f64[0])) / 2)]; + r_.f64[(i * 2) + 1] = b_.f64[i + ((sizeof(r_) / sizeof(r_.f64[0])) / 2)]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpackhi_pd(a, b) simde_mm_unpackhi_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpacklo_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i8 = vzip1q_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(a_.neon_i16)); + int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(b_.neon_i16)); + int8x8x2_t result = vzip_s8(a1, b1); + r_.neon_i8 = vcombine_s8(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i8 = SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, b_.i8, 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i8[0])) / 2) ; i++) { + r_.i8[(i * 2)] = a_.i8[i]; + r_.i8[(i * 2) + 1] = b_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpacklo_epi8(a, b) simde_mm_unpacklo_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpacklo_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vzip1q_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4_t a1 = vget_low_s16(a_.neon_i16); + int16x4_t b1 = vget_low_s16(b_.neon_i16); + int16x4x2_t result = vzip_s16(a1, b1); + r_.neon_i16 = vcombine_s16(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 16, a_.i16, b_.i16, 0, 8, 1, 9, 2, 10, 3, 11); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i16[0])) / 2) ; i++) { + r_.i16[(i * 2)] = a_.i16[i]; + r_.i16[(i * 2) + 1] = b_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpacklo_epi16(a, b) simde_mm_unpacklo_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpacklo_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vzip1q_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x2_t a1 = vget_low_s32(a_.neon_i32); + int32x2_t b1 = vget_low_s32(b_.neon_i32); + int32x2x2_t result = vzip_s32(a1, b1); + r_.neon_i32 = vcombine_s32(result.val[0], result.val[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.i32, b_.i32, 0, 4, 1, 5); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i32[0])) / 2) ; i++) { + r_.i32[(i * 2)] = a_.i32[i]; + r_.i32[(i * 2) + 1] = b_.i32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpacklo_epi32(a, b) simde_mm_unpacklo_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_unpacklo_epi64 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi64(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int64x1_t a_l = vget_low_s64(a_.neon_i64); + int64x1_t b_l = vget_low_s64(b_.neon_i64); + r_.neon_i64 = vcombine_s64(a_l, b_l); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.i64, b_.i64, 0, 2); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.i64[0])) / 2) ; i++) { + r_.i64[(i * 2)] = a_.i64[i]; + r_.i64[(i * 2) + 1] = b_.i64[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpacklo_epi64(a, b) simde_mm_unpacklo_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_unpacklo_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x1_t a_l = vget_low_f64(a_.f64); + float64x1_t b_l = vget_low_f64(b_.f64); + r_.neon_f64 = vcombine_f64(a_l, b_l); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, b_.f64, 0, 2); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_) / sizeof(r_.f64[0])) / 2) ; i++) { + r_.f64[(i * 2)] = a_.f64[i]; + r_.f64[(i * 2) + 1] = b_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_unpacklo_pd(a, b) simde_mm_unpacklo_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_negate_pd(simde__m128d a) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return simde_mm_xor_pd(a, _mm_set1_pd(SIMDE_FLOAT64_C(-0.0))); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(8,1,0)) + r_.altivec_f64 = vec_neg(a_.altivec_f64); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vnegq_f64(a_.neon_f64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_f64x2_neg(a_.wasm_v128); + #elif defined(SIMDE_VECTOR_NEGATE) + r_.f64 = -a_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = -a_.f64[i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_xor_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE2_NATIVE) + return _mm_xor_si128(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = veorq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_xor(a_.altivec_i32, b_.altivec_i32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] ^ b_.i32f[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _mm_xor_si128(a, b) simde_mm_xor_si128(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_not_si128 (simde__m128i a) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) + return _mm_ternarylogic_epi32(a, a, a, 0x55); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vmvnq_s32(a_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i32 = vec_nor(a_.altivec_i32, a_.altivec_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v128_not(a_.wasm_v128); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~(a_.i32f[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} + +#define SIMDE_MM_SHUFFLE2(x, y) (((x) << 1) | (y)) +#if defined(SIMDE_X86_SSE2_ENABLE_NATIVE_ALIASES) + #define _MM_SHUFFLE2(x, y) SIMDE_MM_SHUFFLE2(x, y) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_SSE2_H) */ +/* :: End ../simde/simde/x86/sse2.h :: */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_deinterleaveeven_epi16 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vuzp1q_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8x2_t t = vuzpq_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = t.val[0]; + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 16, a_.i16, b_.i16, 0, 2, 4, 6, 8, 10, 12, 14); + #else + const size_t halfway_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.i16[i] = a_.i16[2 * i]; + r_.i16[i + halfway_point] = b_.i16[2 * i]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_deinterleaveodd_epi16 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vuzp2q_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8x2_t t = vuzpq_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = t.val[1]; + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 16, a_.i16, b_.i16, 1, 3, 5, 7, 9, 11, 13, 15); + #else + const size_t halfway_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.i16[i] = a_.i16[2 * i + 1]; + r_.i16[i + halfway_point] = b_.i16[2 * i + 1]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_deinterleaveeven_epi32 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vuzp1q_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4x2_t t = vuzpq_s32(a_.neon_i32, b_.neon_i32); + r_.neon_i32 = t.val[0]; + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.i32, b_.i32, 0, 2, 4, 6); + #else + const size_t halfway_point = (sizeof(r_.i32) / sizeof(r_.i32[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.i32[i] = a_.i32[2 * i]; + r_.i32[i + halfway_point] = b_.i32[2 * i]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_deinterleaveodd_epi32 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vuzp2q_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4x2_t t = vuzpq_s32(a_.neon_i32, b_.neon_i32); + r_.neon_i32 = t.val[1]; + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.i32, b_.i32, 1, 3, 5, 7); + #else + const size_t halfway_point = (sizeof(r_.i32) / sizeof(r_.i32[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.i32[i] = a_.i32[2 * i + 1]; + r_.i32[i + halfway_point] = b_.i32[2 * i + 1]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_deinterleaveeven_ps (simde__m128 a, simde__m128 b) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vuzp1q_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4x2_t t = vuzpq_f32(a_.neon_f32, b_.neon_f32); + r_.neon_f32 = t.val[0]; + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 0, 2, 4, 6); + #else + const size_t halfway_point = (sizeof(r_.f32) / sizeof(r_.f32[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.f32[i] = a_.f32[2 * i]; + r_.f32[i + halfway_point] = b_.f32[2 * i]; + } + #endif + + return simde__m128_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_x_mm_deinterleaveodd_ps (simde__m128 a, simde__m128 b) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vuzp2q_f32(a_.neon_f32, b_.neon_f32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4x2_t t = vuzpq_f32(a_.neon_f32, b_.neon_f32); + r_.neon_f32 = t.val[1]; + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, b_.f32, 1, 3, 5, 7); + #else + const size_t halfway_point = (sizeof(r_.f32) / sizeof(r_.f32[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.f32[i] = a_.f32[2 * i + 1]; + r_.f32[i + halfway_point] = b_.f32[2 * i + 1]; + } + #endif + + return simde__m128_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_deinterleaveeven_pd (simde__m128d a, simde__m128d b) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vuzp1q_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, b_.f64, 0, 2); + #else + const size_t halfway_point = (sizeof(r_.f64) / sizeof(r_.f64[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.f64[i] = a_.f64[2 * i]; + r_.f64[i + halfway_point] = b_.f64[2 * i]; + } + #endif + + return simde__m128d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_x_mm_deinterleaveodd_pd (simde__m128d a, simde__m128d b) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vuzp2q_f64(a_.neon_f64, b_.neon_f64); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, b_.f64, 1, 3); + #else + const size_t halfway_point = (sizeof(r_.f64) / sizeof(r_.f64[0])) / 2; + for(size_t i = 0 ; i < halfway_point ; i++) { + r_.f64[i] = a_.f64[2 * i + 1]; + r_.f64[i + halfway_point] = b_.f64[2 * i + 1]; + } + #endif + + return simde__m128d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_addsub_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_addsub_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float64x2_t rs = vsubq_f64(a_.neon_f64, b_.neon_f64); + float64x2_t ra = vaddq_f64(a_.neon_f64, b_.neon_f64); + return vcombine_f64(vget_low_f64(rs), vget_high_f64(ra)); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64 - b_.f64, a_.f64 + b_.f64, 0, 3); + #else + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i += 2) { + r_.f64[ i ] = a_.f64[ i ] - b_.f64[ i ]; + r_.f64[1 + i] = a_.f64[1 + i] + b_.f64[1 + i]; + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_addsub_pd(a, b) simde_mm_addsub_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_addsub_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_addsub_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + float32x4_t rs = vsubq_f32(a_.neon_f32, b_.neon_f32); + float32x4_t ra = vaddq_f32(a_.neon_f32, b_.neon_f32); + return vtrn2q_f32(vreinterpretq_f32_s32(vrev64q_s32(vreinterpretq_s32_f32(rs))), ra); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32 - b_.f32, a_.f32 + b_.f32, 0, 5, 2, 7); + #else + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i += 2) { + r_.f32[ i ] = a_.f32[ i ] - b_.f32[ i ]; + r_.f32[1 + i] = a_.f32[1 + i] + b_.f32[1 + i]; + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_addsub_ps(a, b) simde_mm_addsub_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_hadd_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_hadd_pd(a, b); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return simde__m128d_from_neon_f64(vpaddq_f64(simde__m128d_to_neon_f64(a), simde__m128d_to_neon_f64(b))); + #else + return simde_mm_add_pd(simde_x_mm_deinterleaveeven_pd(a, b), simde_x_mm_deinterleaveodd_pd(a, b)); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadd_pd(a, b) simde_mm_hadd_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_hadd_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_hadd_ps(a, b); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return simde__m128_from_neon_f32(vpaddq_f32(simde__m128_to_neon_f32(a), simde__m128_to_neon_f32(b))); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4x2_t t = vuzpq_f32(simde__m128_to_neon_f32(a), simde__m128_to_neon_f32(b)); + return simde__m128_from_neon_f32(vaddq_f32(t.val[0], t.val[1])); + #else + return simde_mm_add_ps(simde_x_mm_deinterleaveeven_ps(a, b), simde_x_mm_deinterleaveodd_ps(a, b)); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadd_ps(a, b) simde_mm_hadd_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_hsub_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_hsub_pd(a, b); + #else + return simde_mm_sub_pd(simde_x_mm_deinterleaveeven_pd(a, b), simde_x_mm_deinterleaveodd_pd(a, b)); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsub_pd(a, b) simde_mm_hsub_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_hsub_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_hsub_ps(a, b); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + float32x4x2_t t = vuzpq_f32(simde__m128_to_neon_f32(a), simde__m128_to_neon_f32(b)); + return simde__m128_from_neon_f32(vaddq_f32(t.val[0], vnegq_f32(t.val[1]))); + #else + return simde_mm_sub_ps(simde_x_mm_deinterleaveeven_ps(a, b), simde_x_mm_deinterleaveodd_ps(a, b)); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsub_ps(a, b) simde_mm_hsub_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_lddqu_si128 (simde__m128i const* mem_addr) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_lddqu_si128(mem_addr); + #else + simde__m128i_private r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vld1q_s32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr)); + #else + simde_memcpy(&r_, mem_addr, sizeof(r_)); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_lddqu_si128(mem_addr) simde_mm_lddqu_si128(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_loaddup_pd (simde_float64 const* mem_addr) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_loaddup_pd(mem_addr); + #else + simde__m128d_private r_; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vdupq_n_f64(*mem_addr); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vdupq_n_s64(*HEDLEY_REINTERPRET_CAST(int64_t const*, mem_addr)); + #else + r_.f64[0] = *mem_addr; + r_.f64[1] = *mem_addr; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_loaddup_pd(mem_addr) simde_mm_loaddup_pd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_movedup_pd (simde__m128d a) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_movedup_pd(a); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vdupq_laneq_f64(a_.neon_f64, 0); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v64x2_shuffle(a_.wasm_v128, a_.wasm_v128, 0, 0); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 16, a_.f64, a_.f64, 0, 0); + #else + r_.f64[0] = a_.f64[0]; + r_.f64[1] = a_.f64[0]; + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_movedup_pd(a) simde_mm_movedup_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_movehdup_ps (simde__m128 a) { + #if defined(SIMDE_X86_SSE3_NATIVE) + return _mm_movehdup_ps(a); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vtrn2q_f32(a_.neon_f32, a_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v32x4_shuffle(a_.wasm_v128, a_.wasm_v128, 1, 1, 3, 3); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, a_.f32, 1, 1, 3, 3); + #else + r_.f32[0] = a_.f32[1]; + r_.f32[1] = a_.f32[1]; + r_.f32[2] = a_.f32[3]; + r_.f32[3] = a_.f32[3]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_movehdup_ps(a) simde_mm_movehdup_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_moveldup_ps (simde__m128 a) { + #if defined(SIMDE__SSE3_NATIVE) + return _mm_moveldup_ps(a); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vtrn1q_f32(a_.neon_f32, a_.neon_f32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_v32x4_shuffle(a_.wasm_v128, a_.wasm_v128, 0, 0, 2, 2); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 16, a_.f32, a_.f32, 0, 0, 2, 2); + #else + r_.f32[0] = a_.f32[0]; + r_.f32[1] = a_.f32[0]; + r_.f32[2] = a_.f32[2]; + r_.f32[3] = a_.f32[2]; + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE3_ENABLE_NATIVE_ALIASES) +# define _mm_moveldup_ps(a) simde_mm_moveldup_ps(a) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_SSE3_H) */ +/* :: End ../simde/simde/x86/sse3.h :: */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_abs_epi8 (simde__m128i a) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_abs_epi8(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_min_epu8(a, _mm_sub_epi8(_mm_setzero_si128(), a)); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vabsq_s8(a_.neon_i8); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_abs(a_.altivec_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_abs(a_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.u8[i] = HEDLEY_STATIC_CAST(uint8_t, (a_.i8[i] < 0) ? (- a_.i8[i]) : a_.i8[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_abs_epi8(a) simde_mm_abs_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_abs_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_abs_epi16(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_max_epi16(a, _mm_sub_epi16(_mm_setzero_si128(), a)); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vabsq_s16(a_.neon_i16); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = vec_abs(a_.altivec_i16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i16x8_abs(a_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, (a_.i16[i] < 0) ? (- a_.i16[i]) : a_.i16[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_abs_epi16(a) simde_mm_abs_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_abs_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_abs_epi32(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + const __m128i m = _mm_cmpgt_epi32(_mm_setzero_si128(), a); + return _mm_sub_epi32(_mm_xor_si128(a, m), m); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vabsq_s32(a_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_abs(a_.altivec_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_abs(a_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + #if defined(_MSC_VER) + HEDLEY_DIAGNOSTIC_PUSH + #pragma warning(disable:4146) + #endif + r_.u32[i] = (a_.i32[i] < 0) ? (- HEDLEY_STATIC_CAST(uint32_t, a_.i32[i])) : HEDLEY_STATIC_CAST(uint32_t, a_.i32[i]); + #if defined(_MSC_VER) + HEDLEY_DIAGNOSTIC_POP + #endif + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_abs_epi32(a) simde_mm_abs_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_abs_pi8 (simde__m64 a) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_abs_pi8(a); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vabs_s8(a_.neon_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.u8[i] = HEDLEY_STATIC_CAST(uint8_t, (a_.i8[i] < 0) ? (- a_.i8[i]) : a_.i8[i]); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_abs_pi8(a) simde_mm_abs_pi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_abs_pi16 (simde__m64 a) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_abs_pi16(a); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i16 = vabs_s16(a_.neon_i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, (a_.i16[i] < 0) ? (- a_.i16[i]) : a_.i16[i]); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_abs_pi16(a) simde_mm_abs_pi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_abs_pi32 (simde__m64 a) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_abs_pi32(a); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vabs_s32(a_.neon_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.u32[i] = HEDLEY_STATIC_CAST(uint32_t, (a_.i32[i] < 0) ? (- a_.i32[i]) : a_.i32[i]); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_abs_pi32(a) simde_mm_abs_pi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_alignr_epi8 (simde__m128i a, simde__m128i b, int count) + SIMDE_REQUIRE_CONSTANT_RANGE(count, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + if (HEDLEY_UNLIKELY(count > 31)) + return simde_mm_setzero_si128(); + + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + const int srcpos = count + HEDLEY_STATIC_CAST(int, i); + if (srcpos > 31) { + r_.i8[i] = 0; + } else if (srcpos > 15) { + r_.i8[i] = a_.i8[(srcpos) & 15]; + } else { + r_.i8[i] = b_.i8[srcpos]; + } + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSSE3_NATIVE) + #define simde_mm_alignr_epi8(a, b, count) _mm_alignr_epi8(a, b, count) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_alignr_epi8(a, b, count) \ + ( \ + ((count) > 31) \ + ? simde__m128i_from_neon_i8(vdupq_n_s8(0)) \ + : ( \ + ((count) > 15) \ + ? (simde__m128i_from_neon_i8(vextq_s8(simde__m128i_to_neon_i8(a), vdupq_n_s8(0), (count) & 15))) \ + : (simde__m128i_from_neon_i8(vextq_s8(simde__m128i_to_neon_i8(b), simde__m128i_to_neon_i8(a), ((count) & 15)))))) +#endif +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) + #define _mm_alignr_epi8(a, b, count) simde_mm_alignr_epi8(a, b, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_alignr_pi8 (simde__m64 a, simde__m64 b, const int count) + SIMDE_REQUIRE_CONSTANT(count) { + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + if (HEDLEY_UNLIKELY(count > 15)) + return simde_mm_setzero_si64(); + + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + const int srcpos = count + HEDLEY_STATIC_CAST(int, i); + if (srcpos > 15) { + r_.i8[i] = 0; + } else if (srcpos > 7) { + r_.i8[i] = a_.i8[(srcpos) & 7]; + } else { + r_.i8[i] = b_.i8[srcpos]; + } + } + + return simde__m64_from_private(r_); +} +#if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) +# define simde_mm_alignr_pi8(a, b, count) _mm_alignr_pi8(a, b, count) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_alignr_pi8(a, b, count) \ + ( \ + ((count) > 15) \ + ? simde__m64_from_neon_i8(vdup_n_s8(0)) \ + : ( \ + ((count) > 7) \ + ? (simde__m64_from_neon_i8(vext_s8(simde__m64_to_neon_i8(a), vdup_n_s8(0), (count) & 7))) \ + : (simde__m64_from_neon_i8(vext_s8(simde__m64_to_neon_i8(b), simde__m64_to_neon_i8(a), ((count) & 7)))))) +#endif +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_alignr_pi8(a, b, count) simde_mm_alignr_pi8(a, b, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_shuffle_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_shuffle_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i8 = vqtbl1q_s8(a_.neon_i8, vandq_u8(b_.neon_u8, vdupq_n_u8(0x8F))); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* Mask out the bits we're not interested in. vtbl will result in 0 + * for any values outside of [0, 15], so if the high bit is set it + * will return 0, just like in SSSE3. */ + b_.neon_i8 = vandq_s8(b_.neon_i8, vdupq_n_s8(HEDLEY_STATIC_CAST(int8_t, (1 << 7) | 15))); + + /* Convert a from an int8x16_t to an int8x8x2_t */ + int8x8x2_t i; + i.val[0] = vget_low_s8(a_.neon_i8); + i.val[1] = vget_high_s8(a_.neon_i8); + + /* Table lookups */ + int8x8_t l = vtbl2_s8(i, vget_low_s8(b_.neon_i8)); + int8x8_t h = vtbl2_s8(i, vget_high_s8(b_.neon_i8)); + + r_.neon_i8 = vcombine_s8(l, h); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + /* This is a bit ugly because of the casts and the awful type + * macros (SIMDE_POWER_ALTIVEC_VECTOR), but it's really just + * vec_sel(vec_perm(a, a, b), 0, vec_cmplt(b, 0)) */ + SIMDE_POWER_ALTIVEC_VECTOR(signed char) z = { 0, }; + SIMDE_POWER_ALTIVEC_VECTOR(signed char) msb_mask = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed char), vec_cmplt(b_.altivec_i8, z)); + SIMDE_POWER_ALTIVEC_VECTOR(signed char) c = vec_perm(a_.altivec_i8, a_.altivec_i8, HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned char), b_.altivec_i8)); + r_.altivec_i8 = vec_sel(c, z, HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned char), msb_mask)); + #else + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[b_.i8[i] & 15] & (~(b_.i8[i]) >> 7); + } + #endif + + return simde__m128i_from_private(r_); +#endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_shuffle_epi8(a, b) simde_mm_shuffle_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_shuffle_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_shuffle_pi8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + b_.neon_i8 = vand_s8(b_.neon_i8, vdup_n_s8(HEDLEY_STATIC_CAST(int8_t, (1 << 7) | 7))); + r_.neon_i8 = vtbl1_s8(a_.neon_i8, b_.neon_i8); + #else + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.i8[i] = a_.i8[b_.i8[i] & 7] & (~(b_.i8[i]) >> 7); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_shuffle_pi8(a, b) simde_mm_shuffle_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_hadd_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_hadd_epi16(a, b); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return simde__m128i_from_neon_i16(vpaddq_s16(simde__m128i_to_neon_i16(a), simde__m128i_to_neon_i16(b))); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8x2_t t = vuzpq_s16(simde__m128i_to_neon_i16(a), simde__m128i_to_neon_i16(b)); + return simde__m128i_from_neon_i16(vaddq_s16(t.val[0], t.val[1])); + #else + return simde_mm_add_epi16(simde_x_mm_deinterleaveeven_epi16(a, b), simde_x_mm_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadd_epi16(a, b) simde_mm_hadd_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_hadd_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_hadd_epi32(a, b); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + return simde__m128i_from_neon_i32(vpaddq_s32(simde__m128i_to_neon_i32(a), simde__m128i_to_neon_i32(b))); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4x2_t t = vuzpq_s32(simde__m128i_to_neon_i32(a), simde__m128i_to_neon_i32(b)); + return simde__m128i_from_neon_i32(vaddq_s32(t.val[0], t.val[1])); + #else + return simde_mm_add_epi32(simde_x_mm_deinterleaveeven_epi32(a, b), simde_x_mm_deinterleaveodd_epi32(a, b)); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadd_epi32(a, b) simde_mm_hadd_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_hadd_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_hadd_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i16 = vpadd_s16(a_.neon_i16, b_.neon_i16); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4x2_t t = vuzp_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = vadd_s16(t.val[0], t.val[1]); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = + SIMDE_SHUFFLE_VECTOR_(16, 8, a_.i16, b_.i16, 0, 2, 4, 6) + + SIMDE_SHUFFLE_VECTOR_(16, 8, a_.i16, b_.i16, 1, 3, 5, 7); + #else + r_.i16[0] = a_.i16[0] + a_.i16[1]; + r_.i16[1] = a_.i16[2] + a_.i16[3]; + r_.i16[2] = b_.i16[0] + b_.i16[1]; + r_.i16[3] = b_.i16[2] + b_.i16[3]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadd_pi16(a, b) simde_mm_hadd_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_hadd_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_hadd_pi32(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_i32 = vpadd_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x2x2_t t = vuzp_s32(a_.neon_i32, b_.neon_i32); + r_.neon_i32 = vadd_s32(t.val[0], t.val[1]); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = + SIMDE_SHUFFLE_VECTOR_(32, 8, a_.i32, b_.i32, 0, 2) + + SIMDE_SHUFFLE_VECTOR_(32, 8, a_.i32, b_.i32, 1, 3); + #else + r_.i32[0] = a_.i32[0] + a_.i32[1]; + r_.i32[1] = b_.i32[0] + b_.i32[1]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadd_pi32(a, b) simde_mm_hadd_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_hadds_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_hadds_epi16(a, b); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8x2_t t = vuzpq_s16(simde__m128i_to_neon_i16(a), simde__m128i_to_neon_i16(b)); + return simde__m128i_from_neon_i16(vqaddq_s16(t.val[0], t.val[1])); + #else + return simde_mm_adds_epi16(simde_x_mm_deinterleaveeven_epi16(a, b), simde_x_mm_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadds_epi16(a, b) simde_mm_hadds_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_hadds_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_hadds_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4x2_t t = vuzp_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = vqadd_s16(t.val[0], t.val[1]); + #else + for (size_t i = 0 ; i < ((sizeof(r_.i16) / sizeof(r_.i16[0])) / 2) ; i++) { + int32_t ta = HEDLEY_STATIC_CAST(int32_t, a_.i16[i * 2]) + HEDLEY_STATIC_CAST(int32_t, a_.i16[(i * 2) + 1]); + r_.i16[ i ] = HEDLEY_LIKELY(ta > INT16_MIN) ? (HEDLEY_LIKELY(ta < INT16_MAX) ? HEDLEY_STATIC_CAST(int16_t, ta) : INT16_MAX) : INT16_MIN; + int32_t tb = HEDLEY_STATIC_CAST(int32_t, b_.i16[i * 2]) + HEDLEY_STATIC_CAST(int32_t, b_.i16[(i * 2) + 1]); + r_.i16[i + 2] = HEDLEY_LIKELY(tb > INT16_MIN) ? (HEDLEY_LIKELY(tb < INT16_MAX) ? HEDLEY_STATIC_CAST(int16_t, tb) : INT16_MAX) : INT16_MIN; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hadds_pi16(a, b) simde_mm_hadds_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_hsub_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_hsub_epi16(a, b); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8x2_t t = vuzpq_s16(simde__m128i_to_neon_i16(a), simde__m128i_to_neon_i16(b)); + return simde__m128i_from_neon_i16(vsubq_s16(t.val[0], t.val[1])); + #else + return simde_mm_sub_epi16(simde_x_mm_deinterleaveeven_epi16(a, b), simde_x_mm_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsub_epi16(a, b) simde_mm_hsub_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_hsub_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_hsub_epi32(a, b); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4x2_t t = vuzpq_s32(simde__m128i_to_neon_i32(a), simde__m128i_to_neon_i32(b)); + return simde__m128i_from_neon_i32(vsubq_s32(t.val[0], t.val[1])); + #else + return simde_mm_sub_epi32(simde_x_mm_deinterleaveeven_epi32(a, b), simde_x_mm_deinterleaveodd_epi32(a, b)); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsub_epi32(a, b) simde_mm_hsub_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_hsub_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_hsub_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4x2_t t = vuzp_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = vsub_s16(t.val[0], t.val[1]); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = + SIMDE_SHUFFLE_VECTOR_(16, 8, a_.i16, b_.i16, 0, 2, 4, 6) - + SIMDE_SHUFFLE_VECTOR_(16, 8, a_.i16, b_.i16, 1, 3, 5, 7); + #else + r_.i16[0] = a_.i16[0] - a_.i16[1]; + r_.i16[1] = a_.i16[2] - a_.i16[3]; + r_.i16[2] = b_.i16[0] - b_.i16[1]; + r_.i16[3] = b_.i16[2] - b_.i16[3]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsub_pi16(a, b) simde_mm_hsub_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_hsub_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_hsub_pi32(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x2x2_t t = vuzp_s32(a_.neon_i32, b_.neon_i32); + r_.neon_i32 = vsub_s32(t.val[0], t.val[1]); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) && defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = + SIMDE_SHUFFLE_VECTOR_(32, 8, a_.i32, b_.i32, 0, 2) - + SIMDE_SHUFFLE_VECTOR_(32, 8, a_.i32, b_.i32, 1, 3); + #else + r_.i32[0] = a_.i32[0] - a_.i32[1]; + r_.i32[1] = b_.i32[0] - b_.i32[1]; + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsub_pi32(a, b) simde_mm_hsub_pi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_hsubs_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_hsubs_epi16(a, b); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8x2_t t = vuzpq_s16(simde__m128i_to_neon_i16(a), simde__m128i_to_neon_i16(b)); + return simde__m128i_from_neon_i16(vqsubq_s16(t.val[0], t.val[1])); + #else + return simde_mm_subs_epi16(simde_x_mm_deinterleaveeven_epi16(a, b), simde_x_mm_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsubs_epi16(a, b) simde_mm_hsubs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_hsubs_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_hsubs_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x4x2_t t = vuzp_s16(a_.neon_i16, b_.neon_i16); + r_.neon_i16 = vqsub_s16(t.val[0], t.val[1]); + #else + for (size_t i = 0 ; i < ((sizeof(r_.i16) / sizeof(r_.i16[0])) / 2) ; i++) { + r_.i16[ i ] = simde_math_subs_i16(a_.i16[i * 2], a_.i16[(i * 2) + 1]); + r_.i16[i + 2] = simde_math_subs_i16(b_.i16[i * 2], b_.i16[(i * 2) + 1]); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_hsubs_pi16(a, b) simde_mm_hsubs_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_maddubs_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_maddubs_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* Zero extend a */ + int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a_.neon_u16, 8)); + int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a_.neon_u16, vdupq_n_u16(0xff00))); + + /* Sign extend by shifting left then shifting right. */ + int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b_.neon_i16, 8), 8); + int16x8_t b_odd = vshrq_n_s16(b_.neon_i16, 8); + + /* multiply */ + int16x8_t prod1 = vmulq_s16(a_even, b_even); + int16x8_t prod2 = vmulq_s16(a_odd, b_odd); + + /* saturated add */ + r_.neon_i16 = vqaddq_s16(prod1, prod2); + #else + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + const int idx = HEDLEY_STATIC_CAST(int, i) << 1; + int32_t ts = + (HEDLEY_STATIC_CAST(int16_t, a_.u8[ idx ]) * HEDLEY_STATIC_CAST(int16_t, b_.i8[ idx ])) + + (HEDLEY_STATIC_CAST(int16_t, a_.u8[idx + 1]) * HEDLEY_STATIC_CAST(int16_t, b_.i8[idx + 1])); + r_.i16[i] = (ts > INT16_MIN) ? ((ts < INT16_MAX) ? HEDLEY_STATIC_CAST(int16_t, ts) : INT16_MAX) : INT16_MIN; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_maddubs_epi16(a, b) simde_mm_maddubs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_maddubs_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_maddubs_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + int16x8_t ai = vreinterpretq_s16_u16(vmovl_u8(a_.neon_u8)); + int16x8_t bi = vmovl_s8(b_.neon_i8); + int16x8_t p = vmulq_s16(ai, bi); + int16x4_t l = vget_low_s16(p); + int16x4_t h = vget_high_s16(p); + r_.neon_i16 = vqadd_s16(vuzp1_s16(l, h), vuzp2_s16(l, h)); + #else + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + const int idx = HEDLEY_STATIC_CAST(int, i) << 1; + int32_t ts = + (HEDLEY_STATIC_CAST(int16_t, a_.u8[ idx ]) * HEDLEY_STATIC_CAST(int16_t, b_.i8[ idx ])) + + (HEDLEY_STATIC_CAST(int16_t, a_.u8[idx + 1]) * HEDLEY_STATIC_CAST(int16_t, b_.i8[idx + 1])); + r_.i16[i] = (ts > INT16_MIN) ? ((ts < INT16_MAX) ? HEDLEY_STATIC_CAST(int16_t, ts) : INT16_MAX) : INT16_MIN; + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_maddubs_pi16(a, b) simde_mm_maddubs_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mulhrs_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_mulhrs_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* Multiply */ + int32x4_t mul_lo = vmull_s16(vget_low_s16(a_.neon_i16), + vget_low_s16(b_.neon_i16)); + int32x4_t mul_hi = vmull_s16(vget_high_s16(a_.neon_i16), + vget_high_s16(b_.neon_i16)); + + /* Rounding narrowing shift right + * narrow = (int16_t)((mul + 16384) >> 15); */ + int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15); + int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15); + + /* Join together */ + r_.neon_i16 = vcombine_s16(narrow_lo, narrow_hi); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, (((HEDLEY_STATIC_CAST(int32_t, a_.i16[i]) * HEDLEY_STATIC_CAST(int32_t, b_.i16[i])) + 0x4000) >> 15)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_mulhrs_epi16(a, b) simde_mm_mulhrs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_mulhrs_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_mulhrs_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* Multiply */ + int32x4_t mul = vmull_s16(a_.neon_i16, b_.neon_i16); + + /* Rounding narrowing shift right + * narrow = (int16_t)((mul + 16384) >> 15); */ + int16x4_t narrow = vrshrn_n_s32(mul, 15); + + /* Join together */ + r_.neon_i16 = narrow; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, (((HEDLEY_STATIC_CAST(int32_t, a_.i16[i]) * HEDLEY_STATIC_CAST(int32_t, b_.i16[i])) + 0x4000) >> 15)); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_mulhrs_pi16(a, b) simde_mm_mulhrs_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sign_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_sign_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint8x16_t aneg_mask = vreinterpretq_u8_s8(vshrq_n_s8(b_.neon_i8, 7)); + uint8x16_t bnz_mask; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + bnz_mask = vceqzq_s8(b_.neon_i8); + #else + bnz_mask = vceqq_s8(b_.neon_i8, vdupq_n_s8(0)); + #endif + bnz_mask = vmvnq_u8(bnz_mask); + + r_.neon_i8 = vbslq_s8(aneg_mask, vnegq_s8(a_.neon_i8), vandq_s8(a_.neon_i8, vreinterpretq_s8_u8(bnz_mask))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + simde__m128i mask = wasm_i8x16_shr(b_.wasm_v128, 7); + simde__m128i zeromask = simde_mm_cmpeq_epi8(b_.wasm_v128, simde_mm_setzero_si128()); + r_.wasm_v128 = simde_mm_andnot_si128(zeromask, simde_mm_xor_si128(simde_mm_add_epi8(a_.wasm_v128, mask), mask)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (b_.i8[i] < 0) ? (- a_.i8[i]) : ((b_.i8[i] != 0) ? (a_.i8[i]) : INT8_C(0)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_sign_epi8(a, b) simde_mm_sign_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sign_epi16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_sign_epi16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint16x8_t aneg_mask = vreinterpretq_u16_s16(vshrq_n_s16(b_.neon_i16, 15)); + uint16x8_t bnz_mask; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + bnz_mask = vceqzq_s16(b_.neon_i16); + #else + bnz_mask = vceqq_s16(b_.neon_i16, vdupq_n_s16(0)); + #endif + bnz_mask = vmvnq_u16(bnz_mask); + + r_.neon_i16 = vbslq_s16(aneg_mask, vnegq_s16(a_.neon_i16), vandq_s16(a_.neon_i16, vreinterpretq_s16_u16(bnz_mask))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + simde__m128i mask = simde_mm_srai_epi16(b_.wasm_v128, 15); + simde__m128i zeromask = simde_mm_cmpeq_epi16(b_.wasm_v128, simde_mm_setzero_si128()); + r_.wasm_v128 = simde_mm_andnot_si128(zeromask, simde_mm_xor_si128(simde_mm_add_epi16(a_.wasm_v128, mask), mask)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (b_.i16[i] < 0) ? (- a_.i16[i]) : ((b_.i16[i] != 0) ? (a_.i16[i]) : INT16_C(0)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_sign_epi16(a, b) simde_mm_sign_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sign_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) + return _mm_sign_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x4_t aneg_mask = vreinterpretq_u32_s32(vshrq_n_s32(b_.neon_i32, 31)); + uint32x4_t bnz_mask; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + bnz_mask = vceqzq_s32(b_.neon_i32); + #else + bnz_mask = vceqq_s32(b_.neon_i32, vdupq_n_s32(0)); + #endif + bnz_mask = vmvnq_u32(bnz_mask); + + r_.neon_i32 = vbslq_s32(aneg_mask, vnegq_s32(a_.neon_i32), vandq_s32(a_.neon_i32, vreinterpretq_s32_u32(bnz_mask))); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + simde__m128i mask = simde_mm_srai_epi32(b_.wasm_v128, 31); + simde__m128i zeromask = simde_mm_cmpeq_epi32(b_.wasm_v128, simde_mm_setzero_si128()); + r_.wasm_v128 = simde_mm_andnot_si128(zeromask, simde_mm_xor_si128(simde_mm_add_epi32(a_.wasm_v128, mask), mask)); + #else + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (b_.i32[i] < 0) ? (- a_.i32[i]) : ((b_.i32[i] != 0) ? (a_.i32[i]) : INT32_C(0)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_sign_epi32(a, b) simde_mm_sign_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sign_pi8 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_sign_pi8(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint8x8_t aneg_mask = vreinterpret_u8_s8(vshr_n_s8(b_.neon_i8, 7)); + uint8x8_t bnz_mask; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + bnz_mask = vceqz_s8(b_.neon_i8); + #else + bnz_mask = vceq_s8(b_.neon_i8, vdup_n_s8(0)); + #endif + bnz_mask = vmvn_u8(bnz_mask); + + r_.neon_i8 = vbsl_s8(aneg_mask, vneg_s8(a_.neon_i8), vand_s8(a_.neon_i8, vreinterpret_s8_u8(bnz_mask))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (b_.i8[i] < 0) ? (- a_.i8[i]) : ((b_.i8[i] != 0) ? (a_.i8[i]) : INT8_C(0)); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_sign_pi8(a, b) simde_mm_sign_pi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sign_pi16 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_sign_pi16(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint16x4_t aneg_mask = vreinterpret_u16_s16(vshr_n_s16(b_.neon_i16, 15)); + uint16x4_t bnz_mask; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + bnz_mask = vceqz_s16(b_.neon_i16); + #else + bnz_mask = vceq_s16(b_.neon_i16, vdup_n_s16(0)); + #endif + bnz_mask = vmvn_u16(bnz_mask); + + r_.neon_i16 = vbsl_s16(aneg_mask, vneg_s16(a_.neon_i16), vand_s16(a_.neon_i16, vreinterpret_s16_u16(bnz_mask))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (b_.i16[i] < 0) ? (- a_.i16[i]) : ((b_.i16[i] > 0) ? (a_.i16[i]) : INT16_C(0)); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_sign_pi16(a, b) simde_mm_sign_pi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m64 +simde_mm_sign_pi32 (simde__m64 a, simde__m64 b) { + #if defined(SIMDE_X86_SSSE3_NATIVE) && defined(SIMDE_X86_MMX_NATIVE) + return _mm_sign_pi32(a, b); + #else + simde__m64_private + r_, + a_ = simde__m64_to_private(a), + b_ = simde__m64_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint32x2_t aneg_mask = vreinterpret_u32_s32(vshr_n_s32(b_.neon_i32, 31)); + uint32x2_t bnz_mask; + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + bnz_mask = vceqz_s32(b_.neon_i32); + #else + bnz_mask = vceq_s32(b_.neon_i32, vdup_n_s32(0)); + #endif + bnz_mask = vmvn_u32(bnz_mask); + + r_.neon_i32 = vbsl_s32(aneg_mask, vneg_s32(a_.neon_i32), vand_s32(a_.neon_i32, vreinterpret_s32_u32(bnz_mask))); + #else + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (b_.i32[i] < 0) ? (- a_.i32[i]) : ((b_.i32[i] > 0) ? (a_.i32[i]) : INT32_C(0)); + } + #endif + + return simde__m64_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSSE3_ENABLE_NATIVE_ALIASES) +# define _mm_sign_pi32(a, b) simde_mm_sign_pi32(a, b) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_SSE2_H) */ +/* :: End ../simde/simde/x86/ssse3.h :: */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +#if !defined(SIMDE_X86_SSE4_1_NATIVE) && defined(SIMDE_ENABLE_NATIVE_ALIASES) +# define SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_blend_epi16 (simde__m128i a, simde__m128i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = ((imm8 >> i) & 1) ? b_.u16[i] : a_.u16[i]; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_blend_epi16(a, b, imm8) _mm_blend_epi16(a, b, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_blend_epi16(a, b, imm8) \ + (__extension__ ({ \ + const uint16_t _mask[8] = { \ + ((imm8) & (1 << 0)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 1)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 2)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 3)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 4)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 5)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 6)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 7)) ? 0xFFFF : 0x0000 \ + }; \ + uint16x8_t _mask_vec = vld1q_u16(_mask); \ + simde__m128i_from_neon_u16(vbslq_u16(_mask_vec, simde__m128i_to_neon_u16(b), simde__m128i_to_neon_u16(a))); \ + })) +#elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) +# define simde_mm_blend_epi16(a, b, imm8) \ + (__extension__ ({ \ + const SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) _mask = { \ + ((imm8) & (1 << 0)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 1)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 2)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 3)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 4)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 5)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 6)) ? 0xFFFF : 0x0000, \ + ((imm8) & (1 << 7)) ? 0xFFFF : 0x0000 \ + }; \ + simde__m128i_from_altivec_u16(vec_sel(simde__m128i_to_altivec_u16(a), simde__m128i_to_altivec_u16(b), _mask)); \ + })) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_blend_epi16 + #define _mm_blend_epi16(a, b, imm8) simde_mm_blend_epi16(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_blend_pd (simde__m128d a, simde__m128d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = ((imm8 >> i) & 1) ? b_.f64[i] : a_.f64[i]; + } + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_blend_pd(a, b, imm8) _mm_blend_pd(a, b, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_blend_pd(a, b, imm8) \ + (__extension__ ({ \ + const uint64_t _mask[2] = { \ + ((imm8) & (1 << 0)) ? UINT64_MAX : 0, \ + ((imm8) & (1 << 1)) ? UINT64_MAX : 0 \ + }; \ + uint64x2_t _mask_vec = vld1q_u64(_mask); \ + simde__m128d_from_neon_u64(vbslq_u64(_mask_vec, simde__m128d_to_neon_u64(b), simde__m128d_to_neon_u64(a))); \ + })) +#elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) +# define simde_mm_blend_pd(a, b, imm8) \ + (__extension__ ({ \ + const SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) _mask = { \ + ((imm8) & (1 << 0)) ? UINT64_MAX : 0, \ + ((imm8) & (1 << 1)) ? UINT64_MAX : 0 \ + }; \ + simde__m128d_from_altivec_f64(vec_sel(simde__m128d_to_altivec_f64(a), simde__m128d_to_altivec_f64(b), _mask)); \ + })) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_blend_pd + #define _mm_blend_pd(a, b, imm8) simde_mm_blend_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_blend_ps (simde__m128 a, simde__m128 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = ((imm8 >> i) & 1) ? b_.f32[i] : a_.f32[i]; + } + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_blend_ps(a, b, imm8) _mm_blend_ps(a, b, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_blend_ps(a, b, imm8) \ + (__extension__ ({ \ + const uint32_t _mask[4] = { \ + ((imm8) & (1 << 0)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 1)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 2)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 3)) ? UINT32_MAX : 0 \ + }; \ + uint32x4_t _mask_vec = vld1q_u32(_mask); \ + simde__m128_from_neon_f32(vbslq_f32(_mask_vec, simde__m128_to_neon_f32(b), simde__m128_to_neon_f32(a))); \ + })) +#elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) +# define simde_mm_blend_ps(a, b, imm8) \ + (__extension__ ({ \ + const SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) _mask = { \ + ((imm8) & (1 << 0)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 1)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 2)) ? UINT32_MAX : 0, \ + ((imm8) & (1 << 3)) ? UINT32_MAX : 0 \ + }; \ + simde__m128_from_altivec_f32(vec_sel(simde__m128_to_altivec_f32(a), simde__m128_to_altivec_f32(b), _mask)); \ + })) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_blend_ps + #define _mm_blend_ps(a, b, imm8) simde_mm_blend_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_blendv_epi8 (simde__m128i a, simde__m128i b, simde__m128i mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_blendv_epi8(a, b, mask); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* Use a signed shift right to create a mask with the sign bit */ + mask_.neon_i8 = vshrq_n_s8(mask_.neon_i8, 7); + r_.neon_i8 = vbslq_s8(mask_.neon_u8, b_.neon_i8, a_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_i8x16_shr(mask_.wasm_v128, 7); + r_.wasm_v128 = wasm_v128_or(wasm_v128_and(b_.wasm_v128, m), wasm_v128_andnot(a_.wasm_v128, m)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_sel(a_.altivec_i8, b_.altivec_i8, vec_cmplt(mask_.altivec_i8, vec_splat_s8(0))); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + /* https://software.intel.com/en-us/forums/intel-c-compiler/topic/850087 */ + #if defined(HEDLEY_INTEL_VERSION_CHECK) + __typeof__(mask_.i8) z = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + mask_.i8 = HEDLEY_STATIC_CAST(__typeof__(mask_.i8), mask_.i8 < z); + #else + mask_.i8 >>= (CHAR_BIT * sizeof(mask_.i8[0])) - 1; + #endif + + r_.i8 = (mask_.i8 & b_.i8) | (~mask_.i8 & a_.i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + int8_t m = mask_.i8[i] >> 7; + r_.i8[i] = (m & b_.i8[i]) | (~m & a_.i8[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_blendv_epi8 + #define _mm_blendv_epi8(a, b, mask) simde_mm_blendv_epi8(a, b, mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_blendv_epi16 (simde__m128i a, simde__m128i b, simde__m128i mask) { + #if defined(SIMDE_X86_SSE2_NATIVE) + mask = simde_mm_srai_epi16(mask, 15); + return simde_mm_or_si128(simde_mm_and_si128(mask, b), simde_mm_andnot_si128(mask, a)); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + mask_ = simde__m128i_to_private(simde_mm_cmplt_epi16(mask, simde_mm_setzero_si128())); + r_.neon_i16 = vbslq_s16(mask_.neon_u16, b_.neon_i16, a_.neon_i16); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i16 = vec_sel(a_.altivec_i16, b_.altivec_i16, vec_cmplt(mask_.altivec_i16, vec_splat_s16(0))); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + #if defined(HEDLEY_INTEL_VERSION_CHECK) + __typeof__(mask_.i16) z = { 0, 0, 0, 0, 0, 0, 0, 0 }; + mask_.i16 = mask_.i16 < z; + #else + mask_.i16 >>= (CHAR_BIT * sizeof(mask_.i16[0])) - 1; + #endif + + r_.i16 = (mask_.i16 & b_.i16) | (~mask_.i16 & a_.i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + int16_t m = mask_.i16[i] >> 15; + r_.i16[i] = (m & b_.i16[i]) | (~m & a_.i16[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_blendv_epi32 (simde__m128i a, simde__m128i b, simde__m128i mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _mm_castsi128_ps(mask))); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + mask_ = simde__m128i_to_private(simde_mm_cmplt_epi32(mask, simde_mm_setzero_si128())); + r_.neon_i32 = vbslq_s32(mask_.neon_u32, b_.neon_i32, a_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_i32x4_shr(mask_.wasm_v128, 31); + r_.wasm_v128 = wasm_v128_or(wasm_v128_and(b_.wasm_v128, m), wasm_v128_andnot(a_.wasm_v128, m)); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_sel(a_.altivec_i32, b_.altivec_i32, vec_cmplt(mask_.altivec_i32, vec_splat_s32(0))); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + #if defined(HEDLEY_INTEL_VERSION_CHECK) + __typeof__(mask_.i32) z = { 0, 0, 0, 0 }; + mask_.i32 = HEDLEY_STATIC_CAST(__typeof__(mask_.i32), mask_.i32 < z); + #else + mask_.i32 >>= (CHAR_BIT * sizeof(mask_.i32[0])) - 1; + #endif + + r_.i32 = (mask_.i32 & b_.i32) | (~mask_.i32 & a_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + int32_t m = mask_.i32[i] >> 31; + r_.i32[i] = (m & b_.i32[i]) | (~m & a_.i32[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_blendv_epi64 (simde__m128i a, simde__m128i b, simde__m128i mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_castpd_si128(_mm_blendv_pd(_mm_castsi128_pd(a), _mm_castsi128_pd(b), _mm_castsi128_pd(mask))); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + mask_.neon_u64 = vcltq_s64(mask_.neon_i64, vdupq_n_s64(UINT64_C(0))); + r_.neon_i64 = vbslq_s64(mask_.neon_u64, b_.neon_i64, a_.neon_i64); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_i64x2_shr(mask_.wasm_v128, 63); + r_.wasm_v128 = wasm_v128_or(wasm_v128_and(b_.wasm_v128, m), wasm_v128_andnot(a_.wasm_v128, m)); + #elif (defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) && !defined(SIMDE_BUG_CLANG_46770)) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i64 = vec_sel(a_.altivec_i64, b_.altivec_i64, vec_cmplt(mask_.altivec_i64, vec_splats(HEDLEY_STATIC_CAST(signed long long, 0)))); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + SIMDE_POWER_ALTIVEC_VECTOR(signed long long) selector = vec_sra(mask_.altivec_i64, vec_splats(HEDLEY_STATIC_CAST(unsigned long long, 63))); + r_.altivec_i32 = vec_sel(a_.altivec_i32, b_.altivec_i32, HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned int), selector)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + #if defined(HEDLEY_INTEL_VERSION_CHECK) + __typeof__(mask_.i64) z = { 0, 0 }; + mask_.i64 = HEDLEY_STATIC_CAST(__typeof__(mask_.i64), mask_.i64 < z); + #else + mask_.i64 >>= (CHAR_BIT * sizeof(mask_.i64[0])) - 1; + #endif + + r_.i64 = (mask_.i64 & b_.i64) | (~mask_.i64 & a_.i64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + int64_t m = mask_.i64[i] >> 63; + r_.i64[i] = (m & b_.i64[i]) | (~m & a_.i64[i]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_blendv_pd (simde__m128d a, simde__m128d b, simde__m128d mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_blendv_pd(a, b, mask); + #else + return simde_mm_castsi128_pd(simde_x_mm_blendv_epi64(simde_mm_castpd_si128(a), simde_mm_castpd_si128(b), simde_mm_castpd_si128(mask))); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_blendv_pd + #define _mm_blendv_pd(a, b, mask) simde_mm_blendv_pd(a, b, mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_blendv_ps (simde__m128 a, simde__m128 b, simde__m128 mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_blendv_ps(a, b, mask); + #else + return simde_mm_castsi128_ps(simde_x_mm_blendv_epi32(simde_mm_castps_si128(a), simde_mm_castps_si128(b), simde_mm_castps_si128(mask))); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_blendv_ps + #define _mm_blendv_ps(a, b, mask) simde_mm_blendv_ps(a, b, mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_round_pd (simde__m128d a, int rounding) + SIMDE_REQUIRE_CONSTANT_RANGE(rounding, 0, 15) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + /* For architectures which lack a current direction SIMD instruction. */ + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + if ((rounding & 7) == SIMDE_MM_FROUND_CUR_DIRECTION) + rounding = HEDLEY_STATIC_CAST(int, SIMDE_MM_GET_ROUNDING_MODE()) << 13; + #endif + + switch (rounding & ~SIMDE_MM_FROUND_NO_EXC) { + case SIMDE_MM_FROUND_CUR_DIRECTION: + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_round(a_.altivec_f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vrndiq_f64(a_.neon_f64); + #elif defined(simde_math_nearbyint) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_nearbyint(a_.f64[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_NEAREST_INT: + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_round(a_.altivec_f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vrndaq_f64(a_.neon_f64); + #elif defined(simde_math_roundeven) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_roundeven(a_.f64[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_NEG_INF: + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_floor(a_.altivec_f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vrndmq_f64(a_.neon_f64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_floor(a_.f64[i]); + } + #endif + break; + + case SIMDE_MM_FROUND_TO_POS_INF: + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_ceil(a_.altivec_f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vrndpq_f64(a_.neon_f64); + #elif defined(simde_math_ceil) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_ceil(a_.f64[i]); + } + #else + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + #endif + break; + + case SIMDE_MM_FROUND_TO_ZERO: + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_f64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(double), vec_trunc(a_.altivec_f64)); + #elif defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vrndq_f64(a_.neon_f64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_trunc(a_.f64[i]); + } + #endif + break; + + default: + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) + #define simde_mm_round_pd(a, rounding) _mm_round_pd(a, rounding) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_round_pd + #define _mm_round_pd(a, rounding) simde_mm_round_pd(a, rounding) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_ceil_pd (simde__m128d a) { + return simde_mm_round_pd(a, SIMDE_MM_FROUND_TO_POS_INF); +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_ceil_pd + #define _mm_ceil_pd(a) simde_mm_ceil_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_ceil_ps (simde__m128 a) { + return simde_mm_round_ps(a, SIMDE_MM_FROUND_TO_POS_INF); +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_ceil_ps + #define _mm_ceil_ps(a) simde_mm_ceil_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_ceil_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_ceil_sd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(simde_math_ceilf) + r_ = simde__m128d_to_private(simde_mm_set_pd(a_.f64[1], simde_math_ceil(b_.f64[0]))); + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_ceil_sd + #define _mm_ceil_sd(a, b) simde_mm_ceil_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_ceil_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_ceil_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_ceil_ps(b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(simde_math_ceilf) + r_ = simde__m128_to_private(simde_mm_set_ps(a_.f32[3], a_.f32[2], a_.f32[1], simde_math_ceilf(b_.f32[0]))); + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_ceil_ss + #define _mm_ceil_ss(a, b) simde_mm_ceil_ss(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpeq_epi64 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cmpeq_epi64(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vceqq_u64(a_.neon_u64, b_.neon_u64); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* (a == b) -> (a_lo == b_lo) && (a_hi == b_hi) */ + uint32x4_t cmp = vceqq_u32(a_.neon_u32, b_.neon_u32); + uint32x4_t swapped = vrev64q_u32(cmp); + r_.neon_u32 = vandq_u32(cmp, swapped); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), a_.i64 == b_.i64); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r_.altivec_i64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(signed long long), vec_cmpeq(a_.altivec_i64, b_.altivec_i64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = (a_.u64[i] == b_.u64[i]) ? ~UINT64_C(0) : UINT64_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cmpeq_epi64 + #define _mm_cmpeq_epi64(a, b) simde_mm_cmpeq_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepi8_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepi8_epi16(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_srai_epi16(_mm_unpacklo_epi8(a, a), 8); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int8x16_t s8x16 = a_.neon_i8; /* xxxx xxxx xxxx DCBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + r_.neon_i16 = s16x8; + #elif defined(SIMDE_SHUFFLE_VECTOR_) && defined(SIMDE_VECTOR_SCALAR) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + r_.i16 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i16), SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, a_.i8, + -1, 0, -1, 1, -1, 2, -1, 3, + -1, 4, -1, 5, -1, 6, -1, 7)); + r_.i16 >>= 8; + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i16, a_.m64_private[0].i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepi8_epi16 + #define _mm_cvtepi8_epi16(a) simde_mm_cvtepi8_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepi8_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepi8_epi32(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + __m128i tmp = _mm_unpacklo_epi8(a, a); + tmp = _mm_unpacklo_epi16(tmp, tmp); + return _mm_srai_epi32(tmp, 24); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int8x16_t s8x16 = a_.neon_i8; /* xxxx xxxx xxxx DCBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */ + r_.neon_i32 = s32x4; + #elif defined(SIMDE_SHUFFLE_VECTOR_) && defined(SIMDE_VECTOR_SCALAR) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + r_.i32 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i32), SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, a_.i8, + -1, -1, -1, 0, -1, -1, -1, 1, + -1, -1, -1, 2, -1, -1, -1, 3)); + r_.i32 >>= 24; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepi8_epi32 + #define _mm_cvtepi8_epi32(a) simde_mm_cvtepi8_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepi8_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepi8_epi64(a); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int8x16_t s8x16 = a_.neon_i8; /* xxxx xxxx xxxx xxBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */ + int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */ + r_.neon_i64 = s64x2; + #elif (!defined(SIMDE_ARCH_X86) && !defined(SIMDE_ARCH_AMD64)) && defined(SIMDE_SHUFFLE_VECTOR_) && defined(SIMDE_VECTOR_SCALAR) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + /* Disabled on x86 due to lack of 64-bit arithmetic shift until + * until AVX-512 (at which point we would be using the native + * _mm_cvtepi_epi64 anyways). */ + r_.i64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i64), SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, a_.i8, + -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, 1)); + r_.i64 >>= 56; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepi8_epi64 + #define _mm_cvtepi8_epi64(a) simde_mm_cvtepi8_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepu8_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepu8_epi16(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi8(a, _mm_setzero_si128()); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint8x16_t u8x16 = a_.neon_u8; /* xxxx xxxx xxxx DCBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + r_.neon_u16 = u16x8; + #elif defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(r_.i8) z = { 0, }; + r_.i16 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i16), SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, z, + 0, 16, 1, 17, 2, 18, 3, 19, + 4, 20, 5, 21, 6, 22, 7, 23)); + #elif defined(SIMDE_CONVERT_VECTOR_) && !defined(SIMDE_BUG_CLANG_45541) && (!defined(SIMDE_ARCH_POWER) || !defined(__clang__)) + SIMDE_CONVERT_VECTOR_(r_.i16, a_.m64_private[0].u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.u8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepu8_epi16 + #define _mm_cvtepu8_epi16(a) simde_mm_cvtepu8_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepu8_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepu8_epi32(a); + #elif defined(SIMDE_X86_SSSE3_NATIVE) + __m128i s = _mm_set_epi8( + 0x80, 0x80, 0x80, 0x03, 0x80, 0x80, 0x80, 0x02, + 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x00); + return _mm_shuffle_epi8(a, s); + #elif defined(SIMDE_X86_SSE2_NATIVE) + __m128i z = _mm_setzero_si128(); + return _mm_unpacklo_epi16(_mm_unpacklo_epi8(a, z), z); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint8x16_t u8x16 = a_.neon_u8; /* xxxx xxxx xxxx DCBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */ + r_.neon_u32 = u32x4; + #elif defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(r_.i8) z = { 0, }; + r_.i32 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i32), SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, z, + 0, 17, 18, 19, 1, 21, 22, 23, + 2, 25, 26, 27, 3, 29, 30, 31)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.u8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepu8_epi32 + #define _mm_cvtepu8_epi32(a) simde_mm_cvtepu8_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepu8_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepu8_epi64(a); + #elif defined(SIMDE_X86_SSSE3_NATIVE) + __m128i s = _mm_set_epi8( + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00); + return _mm_shuffle_epi8(a, s); + #elif defined(SIMDE_X86_SSE2_NATIVE) + __m128i z = _mm_setzero_si128(); + return _mm_unpacklo_epi32(_mm_unpacklo_epi16(_mm_unpacklo_epi8(a, z), z), z); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint8x16_t u8x16 = a_.neon_u8; /* xxxx xxxx xxxx xxBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */ + uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */ + r_.neon_u64 = u64x2; + #elif defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(r_.i8) z = { 0, }; + r_.i64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i64), SIMDE_SHUFFLE_VECTOR_(8, 16, a_.i8, z, + 0, 17, 18, 19, 20, 21, 22, 23, + 1, 25, 26, 27, 28, 29, 30, 31)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.u8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepu8_epi64 + #define _mm_cvtepu8_epi64(a) simde_mm_cvtepu8_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepi16_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepi16_epi32(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_srai_epi32(_mm_unpacklo_epi16(a, a), 16); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vmovl_s16(vget_low_s16(a_.neon_i16)); + #elif !defined(SIMDE_ARCH_X86) && defined(SIMDE_SHUFFLE_VECTOR_) && defined(SIMDE_VECTOR_SCALAR) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + r_.i32 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i32), SIMDE_SHUFFLE_VECTOR_(16, 16, a_.i16, a_.i16, 8, 0, 10, 1, 12, 2, 14, 3)); + r_.i32 >>= 16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepi16_epi32 + #define _mm_cvtepi16_epi32(a) simde_mm_cvtepi16_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepu16_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepu16_epi32(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi16(a, _mm_setzero_si128()); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vmovl_u16(vget_low_u16(a_.neon_u16)); + #elif defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(r_.u16) z = { 0, }; + r_.i32 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i32), SIMDE_SHUFFLE_VECTOR_(16, 16, a_.u16, z, + 0, 9, 1, 11, 2, 13, 3, 15)); + #elif defined(SIMDE_CONVERT_VECTOR_) && !defined(SIMDE_BUG_CLANG_45541) && (!defined(SIMDE_ARCH_POWER) || !defined(__clang__)) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.m64_private[0].u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.u16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepu16_epi32 + #define _mm_cvtepu16_epi32(a) simde_mm_cvtepu16_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepu16_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepu16_epi64(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + __m128i z = _mm_setzero_si128(); + return _mm_unpacklo_epi32(_mm_unpacklo_epi16(a, z), z); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + uint16x8_t u16x8 = a_.neon_u16; /* xxxx xxxx xxxx 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */ + uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */ + r_.neon_u64 = u64x2; + #elif defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(r_.u16) z = { 0, }; + r_.i64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i64), SIMDE_SHUFFLE_VECTOR_(16, 16, a_.u16, z, + 0, 9, 10, 11, + 1, 13, 14, 15)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.u16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepu16_epi64 + #define _mm_cvtepu16_epi64(a) simde_mm_cvtepu16_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepi16_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepi16_epi64(a); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int16x8_t s16x8 = a_.neon_i16; /* xxxx xxxx xxxx 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */ + int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */ + r_.neon_i64 = s64x2; + #elif (!defined(SIMDE_ARCH_X86) && !defined(SIMDE_ARCH_AMD64)) && defined(SIMDE_SHUFFLE_VECTOR_) && defined(SIMDE_VECTOR_SCALAR) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + r_.i64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i64), SIMDE_SHUFFLE_VECTOR_(16, 16, a_.i16, a_.i16, + 8, 9, 10, 0, + 12, 13, 14, 1)); + r_.i64 >>= 48; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepi16_epi64 + #define _mm_cvtepi16_epi64(a) simde_mm_cvtepi16_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepi32_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepi32_epi64(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + __m128i tmp = _mm_shuffle_epi32(a, 0x50); + tmp = _mm_srai_epi32(tmp, 31); + tmp = _mm_shuffle_epi32(tmp, 0xed); + return _mm_unpacklo_epi32(a, tmp); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vmovl_s32(vget_low_s32(a_.neon_i32)); + #elif !defined(SIMDE_ARCH_X86) && defined(SIMDE_SHUFFLE_VECTOR_) && defined(SIMDE_VECTOR_SCALAR) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + r_.i64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i64), SIMDE_SHUFFLE_VECTOR_(32, 16, a_.i32, a_.i32, -1, 0, -1, 1)); + r_.i64 >>= 32; + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i64, a_.m64_private[0].i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepi32_epi64 + #define _mm_cvtepi32_epi64(a) simde_mm_cvtepi32_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cvtepu32_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_cvtepu32_epi64(a); + #elif defined(SIMDE_X86_SSE2_NATIVE) + return _mm_unpacklo_epi32(a, _mm_setzero_si128()); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u64 = vmovl_u32(vget_low_u32(a_.neon_u32)); + #elif defined(SIMDE_VECTOR_SCALAR) && defined(SIMDE_SHUFFLE_VECTOR_) && (SIMDE_ENDIAN_ORDER == SIMDE_ENDIAN_LITTLE) + __typeof__(r_.u32) z = { 0, }; + r_.i64 = HEDLEY_REINTERPRET_CAST(__typeof__(r_.i64), SIMDE_SHUFFLE_VECTOR_(32, 16, a_.u32, z, 0, 4, 1, 6)); + #elif defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i64, a_.m64_private[0].u32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.u32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_cvtepu32_epi64 + #define _mm_cvtepu32_epi64(a) simde_mm_cvtepu32_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_dp_pd (simde__m128d a, simde__m128d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f64 = vmulq_f64(a_.neon_f64, b_.neon_f64); + + switch (imm8) { + case 0xff: + r_.neon_f64 = vaddq_f64(r_.neon_f64, vextq_f64(r_.neon_f64, r_.neon_f64, 1)); + break; + case 0x13: + r_.neon_f64 = vdupq_lane_f64(vget_low_f64(r_.neon_f64), 0); + break; + default: + { /* imm8 is a compile-time constant, so this all becomes just a load */ + uint64_t mask_data[] = { + (imm8 & (1 << 4)) ? ~UINT64_C(0) : UINT64_C(0), + (imm8 & (1 << 5)) ? ~UINT64_C(0) : UINT64_C(0), + }; + r_.neon_f64 = vreinterpretq_f64_u64(vandq_u64(vld1q_u64(mask_data), vreinterpretq_u64_f64(r_.neon_f64))); + } + + r_.neon_f64 = vdupq_n_f64(vaddvq_f64(r_.neon_f64)); + + { + uint64_t mask_data[] = { + (imm8 & 1) ? ~UINT64_C(0) : UINT64_C(0), + (imm8 & 2) ? ~UINT64_C(0) : UINT64_C(0) + }; + r_.neon_f64 = vreinterpretq_f64_u64(vandq_u64(vld1q_u64(mask_data), vreinterpretq_u64_f64(r_.neon_f64))); + } + break; + } + #else + simde_float64 sum = SIMDE_FLOAT64_C(0.0); + + SIMDE_VECTORIZE_REDUCTION(+:sum) + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + sum += ((imm8 >> (i + 4)) & 1) ? (a_.f64[i] * b_.f64[i]) : 0.0; + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = ((imm8 >> i) & 1) ? sum : 0.0; + } + #endif + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_dp_pd(a, b, imm8) _mm_dp_pd(a, b, imm8) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_dp_pd + #define _mm_dp_pd(a, b, imm8) simde_mm_dp_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_dp_ps (simde__m128 a, simde__m128 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_f32 = vmulq_f32(a_.neon_f32, b_.neon_f32); + + switch (imm8) { + case 0xff: + r_.neon_f32 = vdupq_n_f32(vaddvq_f32(r_.neon_f32)); + break; + case 0x7f: + r_.neon_f32 = vsetq_lane_f32(0, r_.neon_f32, 3); + r_.neon_f32 = vdupq_n_f32(vaddvq_f32(r_.neon_f32)); + break; + default: + { + { + uint32_t mask_data[] = { + (imm8 & (1 << 4)) ? ~UINT32_C(0) : UINT32_C(0), + (imm8 & (1 << 5)) ? ~UINT32_C(0) : UINT32_C(0), + (imm8 & (1 << 6)) ? ~UINT32_C(0) : UINT32_C(0), + (imm8 & (1 << 7)) ? ~UINT32_C(0) : UINT32_C(0) + }; + r_.neon_f32 = vreinterpretq_f32_u32(vandq_u32(vld1q_u32(mask_data), vreinterpretq_u32_f32(r_.neon_f32))); + } + + r_.neon_f32 = vdupq_n_f32(vaddvq_f32(r_.neon_f32)); + + { + uint32_t mask_data[] = { + (imm8 & 1) ? ~UINT32_C(0) : UINT32_C(0), + (imm8 & 2) ? ~UINT32_C(0) : UINT32_C(0), + (imm8 & 4) ? ~UINT32_C(0) : UINT32_C(0), + (imm8 & 8) ? ~UINT32_C(0) : UINT32_C(0) + }; + r_.neon_f32 = vreinterpretq_f32_u32(vandq_u32(vld1q_u32(mask_data), vreinterpretq_u32_f32(r_.neon_f32))); + } + } + break; + } + #else + simde_float32 sum = SIMDE_FLOAT32_C(0.0); + + SIMDE_VECTORIZE_REDUCTION(+:sum) + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + sum += ((imm8 >> (i + 4)) & 1) ? (a_.f32[i] * b_.f32[i]) : SIMDE_FLOAT32_C(0.0); + } + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = ((imm8 >> i) & 1) ? sum : SIMDE_FLOAT32_C(0.0); + } + #endif + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_dp_ps(a, b, imm8) _mm_dp_ps(a, b, imm8) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_dp_ps + #define _mm_dp_ps(a, b, imm8) simde_mm_dp_ps(a, b, imm8) +#endif + +#if defined(simde_mm_extract_epi8) +# undef simde_mm_extract_epi8 +#endif +SIMDE_FUNCTION_ATTRIBUTES +int8_t +simde_mm_extract_epi8 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m128i_private + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + (void) imm8; + #endif + return vec_extract(a_.altivec_i8, imm8); + #else + return a_.i8[imm8 & 15]; + #endif +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(SIMDE_BUG_GCC_BAD_MM_EXTRACT_EPI8) +# define simde_mm_extract_epi8(a, imm8) HEDLEY_STATIC_CAST(int8_t, _mm_extract_epi8(a, imm8)) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_extract_epi8(a, imm8) vgetq_lane_s8(simde__m128i_to_private(a).neon_i8, imm8) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_extract_epi8 + #define _mm_extract_epi8(a, imm8) HEDLEY_STATIC_CAST(int, simde_mm_extract_epi8(a, imm8)) +#endif + +#if defined(simde_mm_extract_epi32) +# undef simde_mm_extract_epi32 +#endif +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_extract_epi32 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m128i_private + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + (void) imm8; + #endif + return vec_extract(a_.altivec_i32, imm8); + #else + return a_.i32[imm8 & 3]; + #endif +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_extract_epi32(a, imm8) _mm_extract_epi32(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_extract_epi32(a, imm8) vgetq_lane_s32(simde__m128i_to_private(a).neon_i32, imm8) +#elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) +# define simde_mm_extract_epi32(a, imm8) HEDLEY_STATIC_CAST(int32_t, vec_extract(simde__m128i_to_private(a).altivec_i32, imm8)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_extract_epi32 + #define _mm_extract_epi32(a, imm8) simde_mm_extract_epi32(a, imm8) +#endif + +#if defined(simde_mm_extract_epi64) +# undef simde_mm_extract_epi64 +#endif +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm_extract_epi64 (simde__m128i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m128i_private + a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + #if defined(SIMDE_BUG_GCC_95227) + (void) a_; + (void) imm8; + #endif + return vec_extract(a_.altivec_i64, imm8); + #else + return a_.i64[imm8 & 1]; + #endif +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) && defined(SIMDE_ARCH_AMD64) +# define simde_mm_extract_epi64(a, imm8) _mm_extract_epi64(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_extract_epi64(a, imm8) vgetq_lane_s64(simde__m128i_to_private(a).neon_i64, imm8) +#elif defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) +# define simde_mm_extract_epi64(a, imm8) HEDLEY_STATIC_CAST(int64_t, vec_extract(simde__m128i_to_private(a).altivec_i64, imm8)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #undef _mm_extract_epi64 + #define _mm_extract_epi64(a, imm8) simde_mm_extract_epi64(a, imm8) +#endif + +#if defined(simde_mm_extract_ps) +# undef simde_mm_extract_ps +#endif +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm_extract_ps (simde__m128 a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m128_private + a_ = simde__m128_to_private(a); + + return a_.i32[imm8 & 3]; +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) + #define simde_mm_extract_ps(a, imm8) _mm_extract_ps(a, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + #define simde_mm_extract_ps(a, imm8) vgetq_lane_s32(simde__m128_to_private(a).neon_i32, imm8) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_extract_ps + #define _mm_extract_ps(a, imm8) simde_mm_extract_ps(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_floor_pd (simde__m128d a) { + return simde_mm_round_pd(a, SIMDE_MM_FROUND_TO_NEG_INF); +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_floor_pd + #define _mm_floor_pd(a) simde_mm_floor_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_floor_ps (simde__m128 a) { + return simde_mm_round_ps(a, SIMDE_MM_FROUND_TO_NEG_INF); +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_floor_ps + #define _mm_floor_ps(a) simde_mm_floor_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_floor_sd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_floor_sd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(simde_math_floor) + r_.f64[0] = simde_math_floor(b_.f64[0]); + r_.f64[1] = a_.f64[1]; + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_floor_sd + #define _mm_floor_sd(a, b) simde_mm_floor_sd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_floor_ss (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_floor_ss(a, b); + #elif (SIMDE_NATURAL_VECTOR_SIZE > 0) + return simde_mm_move_ss(a, simde_mm_floor_ps(b)); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(simde_math_floorf) + r_.f32[0] = simde_math_floorf(b_.f32[0]); + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i]; + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_floor_ss + #define _mm_floor_ss(a, b) simde_mm_floor_ss(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_insert_epi8 (simde__m128i a, int i, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m128i_private + r_ = simde__m128i_to_private(a); + + r_.i8[imm8] = HEDLEY_STATIC_CAST(int8_t, i); + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) + /* clang-3.8 returns an incompatible type, so we need the cast. MSVC + * can't handle the cast ("error C2440: 'type cast': cannot convert + * from '__m128i' to '__m128i'"). */ + #if defined(__clang__) + #define simde_mm_insert_epi8(a, i, imm8) HEDLEY_STATIC_CAST(__m128i, _mm_insert_epi8(a, i, imm8)) + #else + #define simde_mm_insert_epi8(a, i, imm8) _mm_insert_epi8(a, i, imm8) + #endif +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_insert_epi8(a, i, imm8) simde__m128i_from_neon_i8(vsetq_lane_s8(i, simde__m128i_to_private(a).i8, imm8)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_insert_epi8 + #define _mm_insert_epi8(a, i, imm8) simde_mm_insert_epi8(a, i, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_insert_epi32 (simde__m128i a, int i, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m128i_private + r_ = simde__m128i_to_private(a); + + r_.i32[imm8] = HEDLEY_STATIC_CAST(int32_t, i); + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) + #if defined(__clang__) + #define simde_mm_insert_epi32(a, i, imm8) HEDLEY_STATIC_CAST(__m128i, _mm_insert_epi32(a, i, imm8)) + #else + #define simde_mm_insert_epi32(a, i, imm8) _mm_insert_epi32(a, i, imm8) + #endif +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_insert_epi32(a, i, imm8) simde__m128i_from_neon_i32(vsetq_lane_s32(i, simde__m128i_to_private(a).i32, imm8)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_insert_epi32 + #define _mm_insert_epi32(a, i, imm8) simde_mm_insert_epi32(a, i, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_insert_epi64 (simde__m128i a, int64_t i, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + #if defined(SIMDE_BUG_GCC_94482) + simde__m128i_private + a_ = simde__m128i_to_private(a); + + switch(imm8) { + case 0: + return simde_mm_set_epi64x(a_.i64[1], i); + break; + case 1: + return simde_mm_set_epi64x(i, a_.i64[0]); + break; + default: + HEDLEY_UNREACHABLE(); + break; + } + #else + simde__m128i_private + r_ = simde__m128i_to_private(a); + + r_.i64[imm8] = i; + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) && defined(SIMDE_ARCH_AMD64) +# define simde_mm_insert_epi64(a, i, imm8) _mm_insert_epi64(a, i, imm8) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm_insert_epi64(a, i, imm8) simde__m128i_from_neon_i64(vsetq_lane_s64(i, simde__m128i_to_private(a).i64, imm8)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #undef _mm_insert_epi64 + #define _mm_insert_epi64(a, i, imm8) simde_mm_insert_epi64(a, i, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_insert_ps (simde__m128 a, simde__m128 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + a_.f32[0] = b_.f32[(imm8 >> 6) & 3]; + a_.f32[(imm8 >> 4) & 3] = a_.f32[0]; + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (imm8 >> i) ? SIMDE_FLOAT32_C(0.0) : a_.f32[i]; + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_insert_ps(a, b, imm8) _mm_insert_ps(a, b, imm8) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_insert_ps + #define _mm_insert_ps(a, b, imm8) simde_mm_insert_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_max_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(__PGI) + return _mm_max_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vmaxq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_max(a_.altivec_i8, b_.altivec_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] > b_.i8[i] ? a_.i8[i] : b_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_max_epi8 + #define _mm_max_epi8(a, b) simde_mm_max_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_max_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(__PGI) + return _mm_max_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vmaxq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_max(a_.altivec_i32, b_.altivec_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] > b_.i32[i] ? a_.i32[i] : b_.i32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_max_epi32 + #define _mm_max_epi32(a, b) simde_mm_max_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_max_epu16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_max_epu16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vmaxq_u16(a_.neon_u16, b_.neon_u16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u16x8_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u16 = vec_max(a_.altivec_u16, b_.altivec_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = a_.u16[i] > b_.u16[i] ? a_.u16[i] : b_.u16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_max_epu16 + #define _mm_max_epu16(a, b) simde_mm_max_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_max_epu32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_max_epu32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vmaxq_u32(a_.neon_u32, b_.neon_u32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u32x4_max(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u32 = vec_max(a_.altivec_u32, b_.altivec_u32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] > b_.u32[i] ? a_.u32[i] : b_.u32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_max_epu32 + #define _mm_max_epu32(a, b) simde_mm_max_epu32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_min_epi8 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(__PGI) + return _mm_min_epi8(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i8 = vminq_s8(a_.neon_i8, b_.neon_i8); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i8x16_min(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i8 = vec_min(a_.altivec_i8, b_.altivec_i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] < b_.i8[i] ? a_.i8[i] : b_.i8[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_min_epi8 + #define _mm_min_epi8(a, b) simde_mm_min_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_min_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) && !defined(__PGI) + return _mm_min_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vminq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_min(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_i32 = vec_min(a_.altivec_i32, b_.altivec_i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] < b_.i32[i] ? a_.i32[i] : b_.i32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_min_epi32 + #define _mm_min_epi32(a, b) simde_mm_min_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_min_epu16 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_min_epu16(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u16 = vminq_u16(a_.neon_u16, b_.neon_u16); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u16x8_min(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u16 = vec_min(a_.altivec_u16, b_.altivec_u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = a_.u16[i] < b_.u16[i] ? a_.u16[i] : b_.u16[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_min_epu16 + #define _mm_min_epu16(a, b) simde_mm_min_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_min_epu32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_min_epu32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vminq_u32(a_.neon_u32, b_.neon_u32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_u32x4_min(a_.wasm_v128, b_.wasm_v128); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) || defined(SIMDE_ZARCH_ZVECTOR_13_NATIVE) + r_.altivec_u32 = vec_min(a_.altivec_u32, b_.altivec_u32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] < b_.u32[i] ? a_.u32[i] : b_.u32[i]; + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_min_epu32 + #define _mm_min_epu32(a, b) simde_mm_min_epu32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_minpos_epu16 (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_minpos_epu16(a); + #else + simde__m128i_private + r_ = simde__m128i_to_private(simde_mm_setzero_si128()), + a_ = simde__m128i_to_private(a); + + r_.u16[0] = UINT16_MAX; + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + if (a_.u16[i] < r_.u16[0]) { + r_.u16[0] = a_.u16[i]; + r_.u16[1] = HEDLEY_STATIC_CAST(uint16_t, i); + } + } + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_minpos_epu16 + #define _mm_minpos_epu16(a) simde_mm_minpos_epu16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mpsadbw_epu8 (simde__m128i a, simde__m128i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + const int a_offset = imm8 & 4; + const int b_offset = (imm8 & 3) << 2; + +#if defined(simde_math_abs) + for (int i = 0 ; i < HEDLEY_STATIC_CAST(int, (sizeof(r_.u16) / sizeof(r_.u16[0]))) ; i++) { + r_.u16[i] = + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset + i + 0] - b_.u8[b_offset + 0]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset + i + 1] - b_.u8[b_offset + 1]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset + i + 2] - b_.u8[b_offset + 2]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset + i + 3] - b_.u8[b_offset + 3]))); + } +#else + HEDLEY_UNREACHABLE(); +#endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_mpsadbw_epu8(a, b, imm8) _mm_mpsadbw_epu8(a, b, imm8) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_mpsadbw_epu8 + #define _mm_mpsadbw_epu8(a, b, imm8) simde_mm_mpsadbw_epu8(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mul_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_mul_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + // vmull_s32 upcasts instead of masking, so we downcast. + int32x2_t a_lo = vmovn_s64(a_.neon_i64); + int32x2_t b_lo = vmovn_s64(b_.neon_i64); + r_.neon_i64 = vmull_s32(a_lo, b_lo); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i64x2_make( + wasm_i32x4_extract_lane(a_.wasm_v128, 0) * HEDLEY_STATIC_CAST(int64_t, wasm_i32x4_extract_lane(b_.wasm_v128, 0)), + wasm_i32x4_extract_lane(a_.wasm_v128, 2) * HEDLEY_STATIC_CAST(int64_t, wasm_i32x4_extract_lane(b_.wasm_v128, 2))); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = + HEDLEY_STATIC_CAST(int64_t, a_.i32[i * 2]) * + HEDLEY_STATIC_CAST(int64_t, b_.i32[i * 2]); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_mul_epi32 + #define _mm_mul_epi32(a, b) simde_mm_mul_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mullo_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_mullo_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vmulq_s32(a_.neon_i32, b_.neon_i32); + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + (void) a_; + (void) b_; + r_.altivec_i32 = vec_mul(a_.altivec_i32, b_.altivec_i32); + #elif defined(SIMDE_WASM_SIMD128_NATIVE) + r_.wasm_v128 = wasm_i32x4_mul(a_.wasm_v128, b_.wasm_v128); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.u32[i] = HEDLEY_STATIC_CAST(uint32_t, (HEDLEY_STATIC_CAST(uint64_t, (HEDLEY_STATIC_CAST(int64_t, a_.i32[i]) * HEDLEY_STATIC_CAST(int64_t, b_.i32[i]))) & 0xffffffff)); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_mullo_epi32 + #define _mm_mullo_epi32(a, b) simde_mm_mullo_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_x_mm_mullo_epu32 (simde__m128i a, simde__m128i b) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vmulq_u32(a_.neon_u32, b_.neon_u32); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.u32 = a_.u32 * b_.u32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] * b_.u32[i]; + } + #endif + + return simde__m128i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_packus_epi32 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_packus_epi32(a, b); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + const int32x4_t z = vdupq_n_s32(0); + r_.neon_u16 = vcombine_u16( + vqmovn_u32(vreinterpretq_u32_s32(vmaxq_s32(z, a_.neon_i32))), + vqmovn_u32(vreinterpretq_u32_s32(vmaxq_s32(z, b_.neon_i32)))); + #else + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.u16[i + 0] = (a_.i32[i] < 0) ? UINT16_C(0) : ((a_.i32[i] > UINT16_MAX) ? (UINT16_MAX) : HEDLEY_STATIC_CAST(uint16_t, a_.i32[i])); + r_.u16[i + 4] = (b_.i32[i] < 0) ? UINT16_C(0) : ((b_.i32[i] > UINT16_MAX) ? (UINT16_MAX) : HEDLEY_STATIC_CAST(uint16_t, b_.i32[i])); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_packus_epi32 + #define _mm_packus_epi32(a, b) simde_mm_packus_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_round_sd (simde__m128d a, simde__m128d b, int rounding) + SIMDE_REQUIRE_CONSTANT_RANGE(rounding, 0, 15) { + simde__m128d_private + r_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + switch (rounding & ~SIMDE_MM_FROUND_NO_EXC) { + #if defined(simde_math_nearbyint) + case SIMDE_MM_FROUND_TO_NEAREST_INT: + case SIMDE_MM_FROUND_CUR_DIRECTION: + r_.f64[0] = simde_math_nearbyint(b_.f64[0]); + break; + #endif + + #if defined(simde_math_floor) + case SIMDE_MM_FROUND_TO_NEG_INF: + r_.f64[0] = simde_math_floor(b_.f64[0]); + break; + #endif + + #if defined(simde_math_ceil) + case SIMDE_MM_FROUND_TO_POS_INF: + r_.f64[0] = simde_math_ceil(b_.f64[0]); + break; + #endif + + #if defined(simde_math_trunc) + case SIMDE_MM_FROUND_TO_ZERO: + r_.f64[0] = simde_math_trunc(b_.f64[0]); + break; + #endif + + default: + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_round_sd(a, b, rounding) _mm_round_sd(a, b, rounding) +#elif SIMDE_NATURAL_VECTOR_SIZE_GE(128) +# define simde_mm_round_sd(a, b, rounding) simde_mm_move_sd(a, simde_mm_round_pd(b, rounding)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_round_sd + #define _mm_round_sd(a, b, rounding) simde_mm_round_sd(a, b, rounding) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_round_ss (simde__m128 a, simde__m128 b, int rounding) + SIMDE_REQUIRE_CONSTANT_RANGE(rounding, 0, 15) { + simde__m128_private + r_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + switch (rounding & ~SIMDE_MM_FROUND_NO_EXC) { + #if defined(simde_math_nearbyintf) + case SIMDE_MM_FROUND_TO_NEAREST_INT: + case SIMDE_MM_FROUND_CUR_DIRECTION: + r_.f32[0] = simde_math_nearbyintf(b_.f32[0]); + break; + #endif + + #if defined(simde_math_floorf) + case SIMDE_MM_FROUND_TO_NEG_INF: + r_.f32[0] = simde_math_floorf(b_.f32[0]); + break; + #endif + + #if defined(simde_math_ceilf) + case SIMDE_MM_FROUND_TO_POS_INF: + r_.f32[0] = simde_math_ceilf(b_.f32[0]); + break; + #endif + + #if defined(simde_math_truncf) + case SIMDE_MM_FROUND_TO_ZERO: + r_.f32[0] = simde_math_truncf(b_.f32[0]); + break; + #endif + + default: + HEDLEY_UNREACHABLE_RETURN(simde_mm_undefined_pd()); + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_SSE4_1_NATIVE) +# define simde_mm_round_ss(a, b, rounding) _mm_round_ss(a, b, rounding) +#elif SIMDE_NATURAL_VECTOR_SIZE_GE(128) +# define simde_mm_round_ss(a, b, rounding) simde_mm_move_ss(a, simde_mm_round_ps(b, rounding)) +#endif +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_round_ss + #define _mm_round_ss(a, b, rounding) simde_mm_round_ss(a, b, rounding) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_stream_load_si128 (const simde__m128i* mem_addr) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_stream_load_si128(HEDLEY_CONST_CAST(simde__m128i*, mem_addr)); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return vreinterpretq_s64_s32(vld1q_s32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr))); + #else + return *mem_addr; + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_stream_load_si128 + #define _mm_stream_load_si128(mem_addr) simde_mm_stream_load_si128(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_test_all_ones (simde__m128i a) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_test_all_ones(a); + #else + simde__m128i_private a_ = simde__m128i_to_private(a); + int r; + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r = vec_all_eq(a_.altivec_i32, vec_splats(~0)); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return r = ((vgetq_lane_s64(a_.neon_i64, 0) & vgetq_lane_s64(a_.neon_i64, 1)) == ~HEDLEY_STATIC_CAST(int64_t, 0)); + #else + int_fast32_t r_ = ~HEDLEY_STATIC_CAST(int_fast32_t, 0); + + SIMDE_VECTORIZE_REDUCTION(&:r_) + for (size_t i = 0 ; i < (sizeof(a_.i32f) / sizeof(a_.i32f[0])) ; i++) { + r_ &= a_.i32f[i]; + } + + r = (r_ == ~HEDLEY_STATIC_CAST(int_fast32_t, 0)); + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_test_all_ones + #define _mm_test_all_ones(a) simde_mm_test_all_ones(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_test_all_zeros (simde__m128i a, simde__m128i mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_test_all_zeros(a, mask); + #else + simde__m128i_private tmp_ = simde__m128i_to_private(simde_mm_and_si128(a, mask)); + int r; + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + r = vec_all_eq(tmp_.altivec_i32, vec_splats(0)); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + return !(vgetq_lane_s64(tmp_.neon_i64, 0) | vgetq_lane_s64(tmp_.neon_i64, 1)); + #else + int_fast32_t r_ = HEDLEY_STATIC_CAST(int_fast32_t, 0); + + SIMDE_VECTORIZE_REDUCTION(|:r_) + for (size_t i = 0 ; i < (sizeof(tmp_.i32f) / sizeof(tmp_.i32f[0])) ; i++) { + r_ |= tmp_.i32f[i]; + } + + r = !r_; + #endif + + return r; + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_test_all_zeros + #define _mm_test_all_zeros(a, mask) simde_mm_test_all_zeros(a, mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_test_mix_ones_zeros (simde__m128i a, simde__m128i mask) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_test_mix_ones_zeros(a, mask); + #else + simde__m128i_private + a_ = simde__m128i_to_private(a), + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int64x2_t s640 = vandq_s64(a_.neon_i64, mask_.neon_i64); + int64x2_t s641 = vandq_s64(vreinterpretq_s64_s32(vmvnq_s32(vreinterpretq_s32_s64(a_.neon_i64))), mask_.neon_i64); + return (((vgetq_lane_s64(s640, 0) | vgetq_lane_s64(s640, 1)) & (vgetq_lane_s64(s641, 0) | vgetq_lane_s64(s641, 1)))!=0); + #else + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) + if (((a_.u64[i] & mask_.u64[i]) != 0) && ((~a_.u64[i] & mask_.u64[i]) != 0)) + return 1; + + return 0; + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_test_mix_ones_zeros + #define _mm_test_mix_ones_zeros(a, mask) simde_mm_test_mix_ones_zeros(a, mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testc_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_testc_si128(a, b); + #else + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int64x2_t s64 = vandq_s64(~a_.neon_i64, b_.neon_i64); + return !(vgetq_lane_s64(s64, 0) & vgetq_lane_s64(s64, 1)); + #else + int_fast32_t r = 0; + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.i32f) / sizeof(a_.i32f[0])) ; i++) { + r |= ~a_.i32f[i] & b_.i32f[i]; + } + + return HEDLEY_STATIC_CAST(int, !r); + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_testc_si128 + #define _mm_testc_si128(a, b) simde_mm_testc_si128(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testnzc_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_testnzc_si128(a, b); + #else + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int64x2_t s640 = vandq_s64(a_.neon_i64, b_.neon_i64); + int64x2_t s641 = vandq_s64(~a_.neon_i64, b_.neon_i64); + return (((vgetq_lane_s64(s640, 0) | vgetq_lane_s64(s640, 1)) & (vgetq_lane_s64(s641, 0) | vgetq_lane_s64(s641, 1)))!=0); + #else + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + if (((a_.u64[i] & b_.u64[i]) != 0) && ((~a_.u64[i] & b_.u64[i]) != 0)) + return 1; + } + + return 0; + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_testnzc_si128 + #define _mm_testnzc_si128(a, b) simde_mm_testnzc_si128(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testz_si128 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_1_NATIVE) + return _mm_testz_si128(a, b); + #else + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int64x2_t s64 = vandq_s64(a_.neon_i64, b_.neon_i64); + return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1)); + #else + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + if ((a_.u64[i] & b_.u64[i]) == 0) + return 1; + } + #endif + + return 0; + #endif +} +#if defined(SIMDE_X86_SSE4_1_ENABLE_NATIVE_ALIASES) + #undef _mm_testz_si128 + #define _mm_testz_si128(a, b) simde_mm_testz_si128(a, b) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_SSE4_1_H) */ +/* :: End ../simde/simde/x86/sse4.1.h :: */ + +#if defined(__ARM_ACLE) || (defined(__GNUC__) && defined(__ARM_FEATURE_CRC32)) + #include +#endif + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +#if defined(SIMDE_X86_SSE4_2_NATIVE) + #define SIMDE_SIDD_UBYTE_OPS _SIDD_UBYTE_OPS + #define SIMDE_SIDD_UWORD_OPS _SIDD_UWORD_OPS + #define SIMDE_SIDD_SBYTE_OPS _SIDD_SBYTE_OPS + #define SIMDE_SIDD_SWORD_OPS _SIDD_SWORD_OPS + #define SIMDE_SIDD_CMP_EQUAL_ANY _SIDD_CMP_EQUAL_ANY + #define SIMDE_SIDD_CMP_RANGES _SIDD_CMP_RANGES + #define SIMDE_SIDD_CMP_EQUAL_EACH _SIDD_CMP_EQUAL_EACH + #define SIMDE_SIDD_CMP_EQUAL_ORDERED _SIDD_CMP_EQUAL_ORDERED + #define SIMDE_SIDD_POSITIVE_POLARITY _SIDD_POSITIVE_POLARITY + #define SIMDE_SIDD_NEGATIVE_POLARITY _SIDD_NEGATIVE_POLARITY + #define SIMDE_SIDD_MASKED_POSITIVE_POLARITY _SIDD_MASKED_POSITIVE_POLARITY + #define SIMDE_SIDD_MASKED_NEGATIVE_POLARITY _SIDD_MASKED_NEGATIVE_POLARITY + #define SIMDE_SIDD_LEAST_SIGNIFICANT _SIDD_LEAST_SIGNIFICANT + #define SIMDE_SIDD_MOST_SIGNIFICANT _SIDD_MOST_SIGNIFICANT + #define SIMDE_SIDD_BIT_MASK _SIDD_BIT_MASK + #define SIMDE_SIDD_UNIT_MASK _SIDD_UNIT_MASK +#else + #define SIMDE_SIDD_UBYTE_OPS 0x00 + #define SIMDE_SIDD_UWORD_OPS 0x01 + #define SIMDE_SIDD_SBYTE_OPS 0x02 + #define SIMDE_SIDD_SWORD_OPS 0x03 + #define SIMDE_SIDD_CMP_EQUAL_ANY 0x00 + #define SIMDE_SIDD_CMP_RANGES 0x04 + #define SIMDE_SIDD_CMP_EQUAL_EACH 0x08 + #define SIMDE_SIDD_CMP_EQUAL_ORDERED 0x0c + #define SIMDE_SIDD_POSITIVE_POLARITY 0x00 + #define SIMDE_SIDD_NEGATIVE_POLARITY 0x10 + #define SIMDE_SIDD_MASKED_POSITIVE_POLARITY 0x20 + #define SIMDE_SIDD_MASKED_NEGATIVE_POLARITY 0x30 + #define SIMDE_SIDD_LEAST_SIGNIFICANT 0x00 + #define SIMDE_SIDD_MOST_SIGNIFICANT 0x40 + #define SIMDE_SIDD_BIT_MASK 0x00 + #define SIMDE_SIDD_UNIT_MASK 0x40 +#endif + +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) && !defined(_SIDD_UBYTE_OPS) + #define _SIDD_UBYTE_OPS SIMDE_SIDD_UBYTE_OPS + #define _SIDD_UWORD_OPS SIMDE_SIDD_UWORD_OPS + #define _SIDD_SBYTE_OPS SIMDE_SIDD_SBYTE_OPS + #define _SIDD_SWORD_OPS SIMDE_SIDD_SWORD_OPS + #define _SIDD_CMP_EQUAL_ANY SIMDE_SIDD_CMP_EQUAL_ANY + #define _SIDD_CMP_RANGES SIMDE_SIDD_CMP_RANGES + #define _SIDD_CMP_EQUAL_EACH SIMDE_SIDD_CMP_EQUAL_EACH + #define _SIDD_CMP_EQUAL_ORDERED SIMDE_SIDD_CMP_EQUAL_ORDERED + #define _SIDD_POSITIVE_POLARITY SIMDE_SIDD_POSITIVE_POLARITY + #define _SIDD_NEGATIVE_POLARITY SIMDE_SIDD_NEGATIVE_POLARITY + #define _SIDD_MASKED_POSITIVE_POLARITY SIMDE_SIDD_MASKED_POSITIVE_POLARITY + #define _SIDD_MASKED_NEGATIVE_POLARITY SIMDE_SIDD_MASKED_NEGATIVE_POLARITY + #define _SIDD_LEAST_SIGNIFICANT SIMDE_SIDD_LEAST_SIGNIFICANT + #define _SIDD_MOST_SIGNIFICANT SIMDE_SIDD_MOST_SIGNIFICANT + #define _SIDD_BIT_MASK SIMDE_SIDD_BIT_MASK + #define _SIDD_UNIT_MASK SIMDE_SIDD_UNIT_MASK +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int simde_mm_cmpestrs (simde__m128i a, int la, simde__m128i b, int lb, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + #if !defined(HEDLEY_PGI_VERSION) + /* https://www.pgroup.com/userforum/viewtopic.php?f=4&p=27590&sid=cf89f8bf30be801831fe4a2ff0a2fa6c */ + (void) a; + (void) b; + #endif + (void) la; + (void) lb; + return la <= ((128 / ((imm8 & SIMDE_SIDD_UWORD_OPS) ? 16 : 8)) - 1); +} +#if defined(SIMDE_X86_SSE4_2_NATIVE) + #define simde_mm_cmpestrs(a, la, b, lb, imm8) _mm_cmpestrs(a, la, b, lb, imm8) +#endif +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #undef _mm_cmpestrs + #define _mm_cmpestrs(a, la, b, lb, imm8) simde_mm_cmpestrs(a, la, b, lb, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int simde_mm_cmpestrz (simde__m128i a, int la, simde__m128i b, int lb, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + #if !defined(HEDLEY_PGI_VERSION) + /* https://www.pgroup.com/userforum/viewtopic.php?f=4&p=27590&sid=cf89f8bf30be801831fe4a2ff0a2fa6c */ + (void) a; + (void) b; + #endif + (void) la; + (void) lb; + return lb <= ((128 / ((imm8 & SIMDE_SIDD_UWORD_OPS) ? 16 : 8)) - 1); +} +#if defined(SIMDE_X86_SSE4_2_NATIVE) + #define simde_mm_cmpestrz(a, la, b, lb, imm8) _mm_cmpestrz(a, la, b, lb, imm8) +#endif +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #undef _mm_cmpestrz + #define _mm_cmpestrz(a, la, b, lb, imm8) simde_mm_cmpestrz(a, la, b, lb, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_cmpgt_epi64 (simde__m128i a, simde__m128i b) { + #if defined(SIMDE_X86_SSE4_2_NATIVE) + return _mm_cmpgt_epi64(a, b); + #elif defined(SIMDE_X86_SSE2_NATIVE) + /* https://stackoverflow.com/a/65175746/501126 */ + __m128i r = _mm_and_si128(_mm_cmpeq_epi32(a, b), _mm_sub_epi64(b, a)); + r = _mm_or_si128(r, _mm_cmpgt_epi32(a, b)); + return _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 3, 1, 1)); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vcgtq_s64(a_.neon_i64, b_.neon_i64); + #elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) + /* https://stackoverflow.com/a/65223269/501126 */ + r_.neon_i64 = vshrq_n_s64(vqsubq_s64(b_.neon_i64, a_.neon_i64), 63); + #elif defined(SIMDE_POWER_ALTIVEC_P8_NATIVE) + r_.altivec_u64 = HEDLEY_REINTERPRET_CAST(SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long), vec_cmpgt(a_.altivec_i64, b_.altivec_i64)); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), a_.i64 > b_.i64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = (a_.i64[i] > b_.i64[i]) ? ~INT64_C(0) : INT64_C(0); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #undef _mm_cmpgt_epi64 + #define _mm_cmpgt_epi64(a, b) simde_mm_cmpgt_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_cmpistrs_8_(simde__m128i a) { + simde__m128i_private a_= simde__m128i_to_private(a); + const int upper_bound = (128 / 8) - 1; + int a_invalid = 0; + SIMDE_VECTORIZE + for (int i = 0 ; i <= upper_bound ; i++) { + if(!a_.i8[i]) + a_invalid = 1; + } + return a_invalid; +} + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_cmpistrs_16_(simde__m128i a) { + simde__m128i_private a_= simde__m128i_to_private(a); + const int upper_bound = (128 / 16) - 1; + int a_invalid = 0; + SIMDE_VECTORIZE + for (int i = 0 ; i <= upper_bound ; i++) { + if(!a_.i16[i]) + a_invalid = 1; + } + return a_invalid; +} + +#if defined(SIMDE_X86_SSE4_2_NATIVE) + #define simde_mm_cmpistrs(a, b, imm8) _mm_cmpistrs(a, b, imm8) +#else + #define simde_mm_cmpistrs(a, b, imm8) \ + (((imm8) & SIMDE_SIDD_UWORD_OPS) \ + ? simde_mm_cmpistrs_16_((a)) \ + : simde_mm_cmpistrs_8_((a))) +#endif +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #undef _mm_cmpistrs + #define _mm_cmpistrs(a, b, imm8) simde_mm_cmpistrs(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_cmpistrz_8_(simde__m128i b) { + simde__m128i_private b_= simde__m128i_to_private(b); + const int upper_bound = (128 / 8) - 1; + int b_invalid = 0; + SIMDE_VECTORIZE + for (int i = 0 ; i <= upper_bound ; i++) { + if(!b_.i8[i]) + b_invalid = 1; + } + return b_invalid; +} + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_cmpistrz_16_(simde__m128i b) { + simde__m128i_private b_= simde__m128i_to_private(b); + const int upper_bound = (128 / 16) - 1; + int b_invalid = 0; + SIMDE_VECTORIZE + for (int i = 0 ; i <= upper_bound ; i++) { + if(!b_.i16[i]) + b_invalid = 1; + } + return b_invalid; +} + +#if defined(SIMDE_X86_SSE4_2_NATIVE) + #define simde_mm_cmpistrz(a, b, imm8) _mm_cmpistrz(a, b, imm8) +#else + #define simde_mm_cmpistrz(a, b, imm8) \ + (((imm8) & SIMDE_SIDD_UWORD_OPS) \ + ? simde_mm_cmpistrz_16_((b)) \ + : simde_mm_cmpistrz_8_((b))) +#endif +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #undef _mm_cmpistrz + #define _mm_cmpistrz(a, b, imm8) simde_mm_cmpistrz(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +uint32_t +simde_mm_crc32_u8(uint32_t prevcrc, uint8_t v) { + #if defined(SIMDE_X86_SSE4_2_NATIVE) + return _mm_crc32_u8(prevcrc, v); + #else + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) && defined(__ARM_FEATURE_CRC32) + return __crc32cb(prevcrc, v); + #else + uint32_t crc = prevcrc; + crc ^= v; + for(int bit = 0 ; bit < 8 ; bit++) { + if (crc & 1) + crc = (crc >> 1) ^ UINT32_C(0x82f63b78); + else + crc = (crc >> 1); + } + return crc; + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #define _mm_crc32_u8(prevcrc, v) simde_mm_crc32_u8(prevcrc, v) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +uint32_t +simde_mm_crc32_u16(uint32_t prevcrc, uint16_t v) { + #if defined(SIMDE_X86_SSE4_2_NATIVE) + return _mm_crc32_u16(prevcrc, v); + #else + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) && defined(__ARM_FEATURE_CRC32) + return __crc32ch(prevcrc, v); + #else + uint32_t crc = prevcrc; + crc = simde_mm_crc32_u8(crc, v & 0xff); + crc = simde_mm_crc32_u8(crc, (v >> 8) & 0xff); + return crc; + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #define _mm_crc32_u16(prevcrc, v) simde_mm_crc32_u16(prevcrc, v) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +uint32_t +simde_mm_crc32_u32(uint32_t prevcrc, uint32_t v) { + #if defined(SIMDE_X86_SSE4_2_NATIVE) + return _mm_crc32_u32(prevcrc, v); + #else + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) && defined(__ARM_FEATURE_CRC32) + return __crc32cw(prevcrc, v); + #else + uint32_t crc = prevcrc; + crc = simde_mm_crc32_u16(crc, v & 0xffff); + crc = simde_mm_crc32_u16(crc, (v >> 16) & 0xffff); + return crc; + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) + #define _mm_crc32_u32(prevcrc, v) simde_mm_crc32_u32(prevcrc, v) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +uint64_t +simde_mm_crc32_u64(uint64_t prevcrc, uint64_t v) { + #if defined(SIMDE_X86_SSE4_2_NATIVE) && defined(SIMDE_ARCH_AMD64) + return _mm_crc32_u64(prevcrc, v); + #else + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) && defined(__ARM_FEATURE_CRC32) + return __crc32cd(HEDLEY_STATIC_CAST(uint32_t, prevcrc), v); + #else + uint64_t crc = prevcrc; + crc = simde_mm_crc32_u32(HEDLEY_STATIC_CAST(uint32_t, crc), v & 0xffffffff); + crc = simde_mm_crc32_u32(HEDLEY_STATIC_CAST(uint32_t, crc), (v >> 32) & 0xffffffff); + return crc; + #endif + #endif +} +#if defined(SIMDE_X86_SSE4_2_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #define _mm_crc32_u64(prevcrc, v) simde_mm_crc32_u64(prevcrc, v) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_SSE4_2_H) */ +/* :: End ../simde/simde/x86/sse4.2.h :: */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_32 int8_t i8 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int16_t i16 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int32_t i32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int64_t i64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint8_t u8 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint16_t u16 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint32_t u32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint64_t u64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_32 simde_int128 i128 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 simde_uint128 u128 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #endif + SIMDE_ALIGN_TO_32 simde_float32 f32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 simde_float64 f64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int_fast32_t i32f SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint_fast32_t u32f SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_32 int8_t i8[32]; + SIMDE_ALIGN_TO_32 int16_t i16[16]; + SIMDE_ALIGN_TO_32 int32_t i32[8]; + SIMDE_ALIGN_TO_32 int64_t i64[4]; + SIMDE_ALIGN_TO_32 uint8_t u8[32]; + SIMDE_ALIGN_TO_32 uint16_t u16[16]; + SIMDE_ALIGN_TO_32 uint32_t u32[8]; + SIMDE_ALIGN_TO_32 uint64_t u64[4]; + SIMDE_ALIGN_TO_32 int_fast32_t i32f[32 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_32 uint_fast32_t u32f[32 / sizeof(uint_fast32_t)]; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_32 simde_int128 i128[2]; + SIMDE_ALIGN_TO_32 simde_uint128 u128[2]; + #endif + SIMDE_ALIGN_TO_32 simde_float32 f32[8]; + SIMDE_ALIGN_TO_32 simde_float64 f64[4]; + #endif + + SIMDE_ALIGN_TO_32 simde__m128_private m128_private[2]; + SIMDE_ALIGN_TO_32 simde__m128 m128[2]; + + #if defined(SIMDE_X86_AVX_NATIVE) + SIMDE_ALIGN_TO_32 __m256 n; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) altivec_u8[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) altivec_u16[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed char) altivec_i8[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed short) altivec_i16[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(int) altivec_i32[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(float) altivec_f32[2]; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) altivec_u64[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(long long) altivec_i64[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(double) altivec_f64[2]; + #endif + #endif +} simde__m256_private; + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_32 int8_t i8 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int16_t i16 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int32_t i32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int64_t i64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint8_t u8 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint16_t u16 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint32_t u32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint64_t u64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_32 simde_int128 i128 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 simde_uint128 u128 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #endif + SIMDE_ALIGN_TO_32 simde_float32 f32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 simde_float64 f64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int_fast32_t i32f SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint_fast32_t u32f SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_32 int8_t i8[32]; + SIMDE_ALIGN_TO_32 int16_t i16[16]; + SIMDE_ALIGN_TO_32 int32_t i32[8]; + SIMDE_ALIGN_TO_32 int64_t i64[4]; + SIMDE_ALIGN_TO_32 uint8_t u8[32]; + SIMDE_ALIGN_TO_32 uint16_t u16[16]; + SIMDE_ALIGN_TO_32 uint32_t u32[8]; + SIMDE_ALIGN_TO_32 uint64_t u64[4]; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_32 simde_int128 i128[2]; + SIMDE_ALIGN_TO_32 simde_uint128 u128[2]; + #endif + SIMDE_ALIGN_TO_32 simde_float32 f32[8]; + SIMDE_ALIGN_TO_32 simde_float64 f64[4]; + SIMDE_ALIGN_TO_32 int_fast32_t i32f[32 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_32 uint_fast32_t u32f[32 / sizeof(uint_fast32_t)]; + #endif + + SIMDE_ALIGN_TO_32 simde__m128d_private m128d_private[2]; + SIMDE_ALIGN_TO_32 simde__m128d m128d[2]; + + #if defined(SIMDE_X86_AVX_NATIVE) + SIMDE_ALIGN_TO_32 __m256d n; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) altivec_u8[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) altivec_u16[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed char) altivec_i8[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed short) altivec_i16[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(float) altivec_f32[2]; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) altivec_u64[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed long long) altivec_i64[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(double) altivec_f64[2]; + #endif + #endif +} simde__m256d_private; + +typedef union { + #if defined(SIMDE_VECTOR_SUBSCRIPT) + SIMDE_ALIGN_TO_32 int8_t i8 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int16_t i16 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int32_t i32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int64_t i64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint8_t u8 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint16_t u16 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint32_t u32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint64_t u64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_32 simde_int128 i128 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 simde_uint128 u128 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #endif + SIMDE_ALIGN_TO_32 simde_float32 f32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 simde_float64 f64 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 int_fast32_t i32f SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + SIMDE_ALIGN_TO_32 uint_fast32_t u32f SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + #else + SIMDE_ALIGN_TO_32 int8_t i8[32]; + SIMDE_ALIGN_TO_32 int16_t i16[16]; + SIMDE_ALIGN_TO_32 int32_t i32[8]; + SIMDE_ALIGN_TO_32 int64_t i64[4]; + SIMDE_ALIGN_TO_32 uint8_t u8[32]; + SIMDE_ALIGN_TO_32 uint16_t u16[16]; + SIMDE_ALIGN_TO_32 uint32_t u32[8]; + SIMDE_ALIGN_TO_32 uint64_t u64[4]; + SIMDE_ALIGN_TO_32 int_fast32_t i32f[32 / sizeof(int_fast32_t)]; + SIMDE_ALIGN_TO_32 uint_fast32_t u32f[32 / sizeof(uint_fast32_t)]; + #if defined(SIMDE_HAVE_INT128_) + SIMDE_ALIGN_TO_32 simde_int128 i128[2]; + SIMDE_ALIGN_TO_32 simde_uint128 u128[2]; + #endif + SIMDE_ALIGN_TO_32 simde_float32 f32[8]; + SIMDE_ALIGN_TO_32 simde_float64 f64[4]; + #endif + + SIMDE_ALIGN_TO_32 simde__m128i_private m128i_private[2]; + SIMDE_ALIGN_TO_32 simde__m128i m128i[2]; + + #if defined(SIMDE_X86_AVX_NATIVE) + SIMDE_ALIGN_TO_32 __m256i n; + #elif defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned char) altivec_u8[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) altivec_u16[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) altivec_u32[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed char) altivec_i8[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed short) altivec_i16[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed int) altivec_i32[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(float) altivec_f32[2]; + #if defined(SIMDE_POWER_ALTIVEC_P7_NATIVE) + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(unsigned long long) altivec_u64[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(signed long long) altivec_i64[2]; + SIMDE_ALIGN_TO_16 SIMDE_POWER_ALTIVEC_VECTOR(double) altivec_f64[2]; + #endif + #endif +} simde__m256i_private; + +#if defined(SIMDE_X86_AVX_NATIVE) + typedef __m256 simde__m256; + typedef __m256i simde__m256i; + typedef __m256d simde__m256d; +#elif defined(SIMDE_VECTOR_SUBSCRIPT) + typedef simde_float32 simde__m256 SIMDE_ALIGN_TO_32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + typedef int_fast32_t simde__m256i SIMDE_ALIGN_TO_32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; + typedef simde_float64 simde__m256d SIMDE_ALIGN_TO_32 SIMDE_VECTOR(32) SIMDE_MAY_ALIAS; +#else + typedef simde__m256_private simde__m256; + typedef simde__m256i_private simde__m256i; + typedef simde__m256d_private simde__m256d; +#endif + +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #if !defined(HEDLEY_INTEL_VERSION) && !defined(_AVXINTRIN_H_INCLUDED) && !defined(__AVXINTRIN_H) && !defined(_CMP_EQ_OQ) + typedef simde__m256 __m256; + typedef simde__m256i __m256i; + typedef simde__m256d __m256d; + #else + #undef __m256 + #define __m256 simde__m256 + #undef __m256i + #define __m256i simde__m256i + #undef __m256d + #define __m256d simde__m256d + #endif +#endif + +HEDLEY_STATIC_ASSERT(32 == sizeof(simde__m256), "simde__m256 size incorrect"); +HEDLEY_STATIC_ASSERT(32 == sizeof(simde__m256_private), "simde__m256_private size incorrect"); +HEDLEY_STATIC_ASSERT(32 == sizeof(simde__m256i), "simde__m256i size incorrect"); +HEDLEY_STATIC_ASSERT(32 == sizeof(simde__m256i_private), "simde__m256i_private size incorrect"); +HEDLEY_STATIC_ASSERT(32 == sizeof(simde__m256d), "simde__m256d size incorrect"); +HEDLEY_STATIC_ASSERT(32 == sizeof(simde__m256d_private), "simde__m256d_private size incorrect"); +#if defined(SIMDE_CHECK_ALIGNMENT) && defined(SIMDE_ALIGN_OF) +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m256) == 32, "simde__m256 is not 32-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m256_private) == 32, "simde__m256_private is not 32-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m256i) == 32, "simde__m256i is not 32-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m256i_private) == 32, "simde__m256i_private is not 32-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m256d) == 32, "simde__m256d is not 32-byte aligned"); +HEDLEY_STATIC_ASSERT(SIMDE_ALIGN_OF(simde__m256d_private) == 32, "simde__m256d_private is not 32-byte aligned"); +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde__m256_from_private(simde__m256_private v) { + simde__m256 r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256_private +simde__m256_to_private(simde__m256 v) { + simde__m256_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde__m256i_from_private(simde__m256i_private v) { + simde__m256i r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i_private +simde__m256i_to_private(simde__m256i v) { + simde__m256i_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde__m256d_from_private(simde__m256d_private v) { + simde__m256d r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d_private +simde__m256d_to_private(simde__m256d v) { + simde__m256d_private r; + simde_memcpy(&r, &v, sizeof(r)); + return r; +} + +#define SIMDE_CMP_EQ_OQ 0 +#define SIMDE_CMP_LT_OS 1 +#define SIMDE_CMP_LE_OS 2 +#define SIMDE_CMP_UNORD_Q 3 +#define SIMDE_CMP_NEQ_UQ 4 +#define SIMDE_CMP_NLT_US 5 +#define SIMDE_CMP_NLE_US 6 +#define SIMDE_CMP_ORD_Q 7 +#define SIMDE_CMP_EQ_UQ 8 +#define SIMDE_CMP_NGE_US 9 +#define SIMDE_CMP_NGT_US 10 +#define SIMDE_CMP_FALSE_OQ 11 +#define SIMDE_CMP_NEQ_OQ 12 +#define SIMDE_CMP_GE_OS 13 +#define SIMDE_CMP_GT_OS 14 +#define SIMDE_CMP_TRUE_UQ 15 +#define SIMDE_CMP_EQ_OS 16 +#define SIMDE_CMP_LT_OQ 17 +#define SIMDE_CMP_LE_OQ 18 +#define SIMDE_CMP_UNORD_S 19 +#define SIMDE_CMP_NEQ_US 20 +#define SIMDE_CMP_NLT_UQ 21 +#define SIMDE_CMP_NLE_UQ 22 +#define SIMDE_CMP_ORD_S 23 +#define SIMDE_CMP_EQ_US 24 +#define SIMDE_CMP_NGE_UQ 25 +#define SIMDE_CMP_NGT_UQ 26 +#define SIMDE_CMP_FALSE_OS 27 +#define SIMDE_CMP_NEQ_OS 28 +#define SIMDE_CMP_GE_OQ 29 +#define SIMDE_CMP_GT_OQ 30 +#define SIMDE_CMP_TRUE_US 31 + +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) && !defined(_CMP_EQ_OQ) +#define _CMP_EQ_OQ SIMDE_CMP_EQ_OQ +#define _CMP_LT_OS SIMDE_CMP_LT_OS +#define _CMP_LE_OS SIMDE_CMP_LE_OS +#define _CMP_UNORD_Q SIMDE_CMP_UNORD_Q +#define _CMP_NEQ_UQ SIMDE_CMP_NEQ_UQ +#define _CMP_NLT_US SIMDE_CMP_NLT_US +#define _CMP_NLE_US SIMDE_CMP_NLE_US +#define _CMP_ORD_Q SIMDE_CMP_ORD_Q +#define _CMP_EQ_UQ SIMDE_CMP_EQ_UQ +#define _CMP_NGE_US SIMDE_CMP_NGE_US +#define _CMP_NGT_US SIMDE_CMP_NGT_US +#define _CMP_FALSE_OQ SIMDE_CMP_FALSE_OQ +#define _CMP_NEQ_OQ SIMDE_CMP_NEQ_OQ +#define _CMP_GE_OS SIMDE_CMP_GE_OS +#define _CMP_GT_OS SIMDE_CMP_GT_OS +#define _CMP_TRUE_UQ SIMDE_CMP_TRUE_UQ +#define _CMP_EQ_OS SIMDE_CMP_EQ_OS +#define _CMP_LT_OQ SIMDE_CMP_LT_OQ +#define _CMP_LE_OQ SIMDE_CMP_LE_OQ +#define _CMP_UNORD_S SIMDE_CMP_UNORD_S +#define _CMP_NEQ_US SIMDE_CMP_NEQ_US +#define _CMP_NLT_UQ SIMDE_CMP_NLT_UQ +#define _CMP_NLE_UQ SIMDE_CMP_NLE_UQ +#define _CMP_ORD_S SIMDE_CMP_ORD_S +#define _CMP_EQ_US SIMDE_CMP_EQ_US +#define _CMP_NGE_UQ SIMDE_CMP_NGE_UQ +#define _CMP_NGT_UQ SIMDE_CMP_NGT_UQ +#define _CMP_FALSE_OS SIMDE_CMP_FALSE_OS +#define _CMP_NEQ_OS SIMDE_CMP_NEQ_OS +#define _CMP_GE_OQ SIMDE_CMP_GE_OQ +#define _CMP_GT_OQ SIMDE_CMP_GT_OQ +#define _CMP_TRUE_US SIMDE_CMP_TRUE_US +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_castps_pd (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castps_pd(a); + #else + return *HEDLEY_REINTERPRET_CAST(simde__m256d*, &a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castps_pd + #define _mm256_castps_pd(a) simde_mm256_castps_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_castps_si256 (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castps_si256(a); + #else + return *HEDLEY_REINTERPRET_CAST(simde__m256i*, &a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castps_si256 + #define _mm256_castps_si256(a) simde_mm256_castps_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_castsi256_pd (simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castsi256_pd(a); + #else + return *HEDLEY_REINTERPRET_CAST(simde__m256d*, &a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castsi256_pd + #define _mm256_castsi256_pd(a) simde_mm256_castsi256_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_castsi256_ps (simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castsi256_ps(a); + #else + return *HEDLEY_REINTERPRET_CAST(simde__m256*, &a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castsi256_ps + #define _mm256_castsi256_ps(a) simde_mm256_castsi256_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_castpd_ps (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castpd_ps(a); + #else + return *HEDLEY_REINTERPRET_CAST(simde__m256*, &a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castpd_ps + #define _mm256_castpd_ps(a) simde_mm256_castpd_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_castpd_si256 (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castpd_si256(a); + #else + return *HEDLEY_REINTERPRET_CAST(simde__m256i*, &a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castpd_si256 + #define _mm256_castpd_si256(a) simde_mm256_castpd_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_setzero_si256 (void) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setzero_si256(); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_setzero_si128(); + r_.m128i[1] = simde_mm_setzero_si128(); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = 0; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setzero_si256 + #define _mm256_setzero_si256() simde_mm256_setzero_si256() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_setzero_ps (void) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setzero_ps(); + #else + return simde_mm256_castsi256_ps(simde_mm256_setzero_si256()); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setzero_ps + #define _mm256_setzero_ps() simde_mm256_setzero_ps() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_setzero_pd (void) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setzero_pd(); + #else + return simde_mm256_castsi256_pd(simde_mm256_setzero_si256()); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setzero_pd + #define _mm256_setzero_pd() simde_mm256_setzero_pd() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_not_ps(simde__m256 a) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = ~a_.i32; + #elif SIMDE_NATURAL_VECTOR_SIZE_GE(128) + r_.m128[0] = simde_x_mm_not_ps(a_.m128[0]); + r_.m128[1] = simde_x_mm_not_ps(a_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = ~(a_.i32[i]); + } + #endif + + return simde__m256_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_select_ps(simde__m256 a, simde__m256 b, simde__m256 mask) { + /* This function is for when you want to blend two elements together + * according to a mask. It is similar to _mm256_blendv_ps, except that + * it is undefined whether the blend is based on the highest bit in + * each lane (like blendv) or just bitwise operations. This allows + * us to implement the function efficiently everywhere. + * + * Basically, you promise that all the lanes in mask are either 0 or + * ~0. */ + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_blendv_ps(a, b, mask); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b), + mask_ = simde__m256_to_private(mask); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 ^ ((a_.i32 ^ b_.i32) & mask_.i32); + #elif SIMDE_NATURAL_VECTOR_SIZE_GE(128) + r_.m128[0] = simde_x_mm_select_ps(a_.m128[0], b_.m128[0], mask_.m128[0]); + r_.m128[1] = simde_x_mm_select_ps(a_.m128[1], b_.m128[1], mask_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] ^ ((a_.i32[i] ^ b_.i32[i]) & mask_.i32[i]); + } + #endif + + return simde__m256_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_not_pd(simde__m256d a) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = ~a_.i64; + #elif SIMDE_NATURAL_VECTOR_SIZE_GE(128) + r_.m128d[0] = simde_x_mm_not_pd(a_.m128d[0]); + r_.m128d[1] = simde_x_mm_not_pd(a_.m128d[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = ~(a_.i64[i]); + } + #endif + + return simde__m256d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_select_pd(simde__m256d a, simde__m256d b, simde__m256d mask) { + /* This function is for when you want to blend two elements together + * according to a mask. It is similar to _mm256_blendv_pd, except that + * it is undefined whether the blend is based on the highest bit in + * each lane (like blendv) or just bitwise operations. This allows + * us to implement the function efficiently everywhere. + * + * Basically, you promise that all the lanes in mask are either 0 or + * ~0. */ + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_blendv_pd(a, b, mask); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b), + mask_ = simde__m256d_to_private(mask); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 ^ ((a_.i64 ^ b_.i64) & mask_.i64); + #elif SIMDE_NATURAL_VECTOR_SIZE_GE(128) + r_.m128d[0] = simde_x_mm_select_pd(a_.m128d[0], b_.m128d[0], mask_.m128d[0]); + r_.m128d[1] = simde_x_mm_select_pd(a_.m128d[1], b_.m128d[1], mask_.m128d[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] ^ ((a_.i64[i] ^ b_.i64[i]) & mask_.i64[i]); + } + #endif + + return simde__m256d_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_setone_si256 (void) { + simde__m256i_private r_; + +#if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + __typeof__(r_.i32f) rv = { 0, }; + r_.i32f = ~rv; +#elif defined(SIMDE_X86_AVX2_NATIVE) + __m256i t = _mm256_setzero_si256(); + r_.n = _mm256_cmpeq_epi32(t, t); +#else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~HEDLEY_STATIC_CAST(int_fast32_t, 0); + } +#endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_setone_ps (void) { + return simde_mm256_castsi256_ps(simde_x_mm256_setone_si256()); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_setone_pd (void) { + return simde_mm256_castsi256_pd(simde_x_mm256_setone_si256()); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set_epi8 (int8_t e31, int8_t e30, int8_t e29, int8_t e28, + int8_t e27, int8_t e26, int8_t e25, int8_t e24, + int8_t e23, int8_t e22, int8_t e21, int8_t e20, + int8_t e19, int8_t e18, int8_t e17, int8_t e16, + int8_t e15, int8_t e14, int8_t e13, int8_t e12, + int8_t e11, int8_t e10, int8_t e9, int8_t e8, + int8_t e7, int8_t e6, int8_t e5, int8_t e4, + int8_t e3, int8_t e2, int8_t e1, int8_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_epi8(e31, e30, e29, e28, e27, e26, e25, e24, + e23, e22, e21, e20, e19, e18, e17, e16, + e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set_epi8( + e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + r_.m128i[1] = simde_mm_set_epi8( + e31, e30, e29, e28, e27, e26, e25, e24, + e23, e22, e21, e20, e19, e18, e17, e16); + #else + r_.i8[ 0] = e0; + r_.i8[ 1] = e1; + r_.i8[ 2] = e2; + r_.i8[ 3] = e3; + r_.i8[ 4] = e4; + r_.i8[ 5] = e5; + r_.i8[ 6] = e6; + r_.i8[ 7] = e7; + r_.i8[ 8] = e8; + r_.i8[ 9] = e9; + r_.i8[10] = e10; + r_.i8[11] = e11; + r_.i8[12] = e12; + r_.i8[13] = e13; + r_.i8[14] = e14; + r_.i8[15] = e15; + r_.i8[16] = e16; + r_.i8[17] = e17; + r_.i8[18] = e18; + r_.i8[19] = e19; + r_.i8[20] = e20; + r_.i8[21] = e21; + r_.i8[22] = e22; + r_.i8[23] = e23; + r_.i8[24] = e24; + r_.i8[25] = e25; + r_.i8[26] = e26; + r_.i8[27] = e27; + r_.i8[28] = e28; + r_.i8[29] = e29; + r_.i8[30] = e30; + r_.i8[31] = e31; + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_epi8 + #define _mm256_set_epi8(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_set_epi8(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set_epi16 (int16_t e15, int16_t e14, int16_t e13, int16_t e12, + int16_t e11, int16_t e10, int16_t e9, int16_t e8, + int16_t e7, int16_t e6, int16_t e5, int16_t e4, + int16_t e3, int16_t e2, int16_t e1, int16_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_epi16(e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set_epi16( e7, e6, e5, e4, e3, e2, e1, e0); + r_.m128i[1] = simde_mm_set_epi16(e15, e14, e13, e12, e11, e10, e9, e8); + #else + r_.i16[ 0] = e0; + r_.i16[ 1] = e1; + r_.i16[ 2] = e2; + r_.i16[ 3] = e3; + r_.i16[ 4] = e4; + r_.i16[ 5] = e5; + r_.i16[ 6] = e6; + r_.i16[ 7] = e7; + r_.i16[ 8] = e8; + r_.i16[ 9] = e9; + r_.i16[10] = e10; + r_.i16[11] = e11; + r_.i16[12] = e12; + r_.i16[13] = e13; + r_.i16[14] = e14; + r_.i16[15] = e15; + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_epi16 + #define _mm256_set_epi16(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_set_epi16(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set_epi32 (int32_t e7, int32_t e6, int32_t e5, int32_t e4, + int32_t e3, int32_t e2, int32_t e1, int32_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_epi32(e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set_epi32(e3, e2, e1, e0); + r_.m128i[1] = simde_mm_set_epi32(e7, e6, e5, e4); + #else + r_.i32[ 0] = e0; + r_.i32[ 1] = e1; + r_.i32[ 2] = e2; + r_.i32[ 3] = e3; + r_.i32[ 4] = e4; + r_.i32[ 5] = e5; + r_.i32[ 6] = e6; + r_.i32[ 7] = e7; + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_epi32 + #define _mm256_set_epi32(e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_set_epi32(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set_epi64x (int64_t e3, int64_t e2, int64_t e1, int64_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_epi64x(e3, e2, e1, e0); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set_epi64x(e1, e0); + r_.m128i[1] = simde_mm_set_epi64x(e3, e2); + #else + r_.i64[0] = e0; + r_.i64[1] = e1; + r_.i64[2] = e2; + r_.i64[3] = e3; + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_epi64x + #define _mm256_set_epi64x(e3, e2, e1, e0) simde_mm256_set_epi64x(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_set_epu8 (uint8_t e31, uint8_t e30, uint8_t e29, uint8_t e28, + uint8_t e27, uint8_t e26, uint8_t e25, uint8_t e24, + uint8_t e23, uint8_t e22, uint8_t e21, uint8_t e20, + uint8_t e19, uint8_t e18, uint8_t e17, uint8_t e16, + uint8_t e15, uint8_t e14, uint8_t e13, uint8_t e12, + uint8_t e11, uint8_t e10, uint8_t e9, uint8_t e8, + uint8_t e7, uint8_t e6, uint8_t e5, uint8_t e4, + uint8_t e3, uint8_t e2, uint8_t e1, uint8_t e0) { + simde__m256i_private r_; + + r_.u8[ 0] = e0; + r_.u8[ 1] = e1; + r_.u8[ 2] = e2; + r_.u8[ 3] = e3; + r_.u8[ 4] = e4; + r_.u8[ 5] = e5; + r_.u8[ 6] = e6; + r_.u8[ 7] = e7; + r_.u8[ 8] = e8; + r_.u8[ 9] = e9; + r_.u8[10] = e10; + r_.u8[11] = e11; + r_.u8[12] = e12; + r_.u8[13] = e13; + r_.u8[14] = e14; + r_.u8[15] = e15; + r_.u8[16] = e16; + r_.u8[17] = e17; + r_.u8[18] = e18; + r_.u8[19] = e19; + r_.u8[20] = e20; + r_.u8[20] = e20; + r_.u8[21] = e21; + r_.u8[22] = e22; + r_.u8[23] = e23; + r_.u8[24] = e24; + r_.u8[25] = e25; + r_.u8[26] = e26; + r_.u8[27] = e27; + r_.u8[28] = e28; + r_.u8[29] = e29; + r_.u8[30] = e30; + r_.u8[31] = e31; + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_set_epu16 (uint16_t e15, uint16_t e14, uint16_t e13, uint16_t e12, + uint16_t e11, uint16_t e10, uint16_t e9, uint16_t e8, + uint16_t e7, uint16_t e6, uint16_t e5, uint16_t e4, + uint16_t e3, uint16_t e2, uint16_t e1, uint16_t e0) { + simde__m256i_private r_; + + r_.u16[ 0] = e0; + r_.u16[ 1] = e1; + r_.u16[ 2] = e2; + r_.u16[ 3] = e3; + r_.u16[ 4] = e4; + r_.u16[ 5] = e5; + r_.u16[ 6] = e6; + r_.u16[ 7] = e7; + r_.u16[ 8] = e8; + r_.u16[ 9] = e9; + r_.u16[10] = e10; + r_.u16[11] = e11; + r_.u16[12] = e12; + r_.u16[13] = e13; + r_.u16[14] = e14; + r_.u16[15] = e15; + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_set_epu32 (uint32_t e7, uint32_t e6, uint32_t e5, uint32_t e4, + uint32_t e3, uint32_t e2, uint32_t e1, uint32_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_epi32(HEDLEY_STATIC_CAST(int32_t, e7), HEDLEY_STATIC_CAST(int32_t, e6), HEDLEY_STATIC_CAST(int32_t, e5), HEDLEY_STATIC_CAST(int32_t, e4), + HEDLEY_STATIC_CAST(int32_t, e3), HEDLEY_STATIC_CAST(int32_t, e2), HEDLEY_STATIC_CAST(int32_t, e1), HEDLEY_STATIC_CAST(int32_t, e0)); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set_epi32(HEDLEY_STATIC_CAST(int32_t, e3), HEDLEY_STATIC_CAST(int32_t, e2), HEDLEY_STATIC_CAST(int32_t, e1), HEDLEY_STATIC_CAST(int32_t, e0)); + r_.m128i[1] = simde_mm_set_epi32(HEDLEY_STATIC_CAST(int32_t, e7), HEDLEY_STATIC_CAST(int32_t, e6), HEDLEY_STATIC_CAST(int32_t, e5), HEDLEY_STATIC_CAST(int32_t, e4)); + #else + r_.u32[ 0] = e0; + r_.u32[ 1] = e1; + r_.u32[ 2] = e2; + r_.u32[ 3] = e3; + r_.u32[ 4] = e4; + r_.u32[ 5] = e5; + r_.u32[ 6] = e6; + r_.u32[ 7] = e7; + #endif + + return simde__m256i_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_set_epu64x (uint64_t e3, uint64_t e2, uint64_t e1, uint64_t e0) { + simde__m256i_private r_; + + r_.u64[0] = e0; + r_.u64[1] = e1; + r_.u64[2] = e2; + r_.u64[3] = e3; + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_set_ps (simde_float32 e7, simde_float32 e6, simde_float32 e5, simde_float32 e4, + simde_float32 e3, simde_float32 e2, simde_float32 e1, simde_float32 e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_ps(e7, e6, e5, e4, e3, e2, e1, e0); + #else + simde__m256_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_set_ps(e3, e2, e1, e0); + r_.m128[1] = simde_mm_set_ps(e7, e6, e5, e4); + #else + r_.f32[0] = e0; + r_.f32[1] = e1; + r_.f32[2] = e2; + r_.f32[3] = e3; + r_.f32[4] = e4; + r_.f32[5] = e5; + r_.f32[6] = e6; + r_.f32[7] = e7; + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_ps + #define _mm256_set_ps(e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_set_ps(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_set_pd (simde_float64 e3, simde_float64 e2, simde_float64 e1, simde_float64 e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set_pd(e3, e2, e1, e0); + #else + simde__m256d_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_set_pd(e1, e0); + r_.m128d[1] = simde_mm_set_pd(e3, e2); + #else + r_.f64[0] = e0; + r_.f64[1] = e1; + r_.f64[2] = e2; + r_.f64[3] = e3; + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_pd + #define _mm256_set_pd(e3, e2, e1, e0) \ + simde_mm256_set_pd(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_set_m128 (simde__m128 e1, simde__m128 e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_insertf128_ps(_mm256_castps128_ps256(e0), e1, 1); + #else + simde__m256_private r_; + simde__m128_private + e1_ = simde__m128_to_private(e1), + e0_ = simde__m128_to_private(e0); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128_private[0] = e0_; + r_.m128_private[1] = e1_; + #elif defined(SIMDE_HAVE_INT128_) + r_.i128[0] = e0_.i128[0]; + r_.i128[1] = e1_.i128[0]; + #else + r_.i64[0] = e0_.i64[0]; + r_.i64[1] = e0_.i64[1]; + r_.i64[2] = e1_.i64[0]; + r_.i64[3] = e1_.i64[1]; + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_m128 + #define _mm256_set_m128(e1, e0) simde_mm256_set_m128(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_set_m128d (simde__m128d e1, simde__m128d e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_insertf128_pd(_mm256_castpd128_pd256(e0), e1, 1); + #else + simde__m256d_private r_; + simde__m128d_private + e1_ = simde__m128d_to_private(e1), + e0_ = simde__m128d_to_private(e0); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d_private[0] = e0_; + r_.m128d_private[1] = e1_; + #else + r_.i64[0] = e0_.i64[0]; + r_.i64[1] = e0_.i64[1]; + r_.i64[2] = e1_.i64[0]; + r_.i64[3] = e1_.i64[1]; + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_m128d + #define _mm256_set_m128d(e1, e0) simde_mm256_set_m128d(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set_m128i (simde__m128i e1, simde__m128i e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_insertf128_si256(_mm256_castsi128_si256(e0), e1, 1); + #else + simde__m256i_private r_; + simde__m128i_private + e1_ = simde__m128i_to_private(e1), + e0_ = simde__m128i_to_private(e0); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i_private[0] = e0_; + r_.m128i_private[1] = e1_; + #else + r_.i64[0] = e0_.i64[0]; + r_.i64[1] = e0_.i64[1]; + r_.i64[2] = e1_.i64[0]; + r_.i64[3] = e1_.i64[1]; + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set_m128i + #define _mm256_set_m128i(e1, e0) simde_mm256_set_m128i(e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set1_epi8 (int8_t a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set1_epi8(a); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set1_epi8(a); + r_.m128i[1] = simde_mm_set1_epi8(a); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set1_epi8 + #define _mm256_set1_epi8(a) simde_mm256_set1_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set1_epi16 (int16_t a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set1_epi16(a); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set1_epi16(a); + r_.m128i[1] = simde_mm_set1_epi16(a); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set1_epi16 + #define _mm256_set1_epi16(a) simde_mm256_set1_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set1_epi32 (int32_t a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set1_epi32(a); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set1_epi32(a); + r_.m128i[1] = simde_mm_set1_epi32(a); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set1_epi32 + #define _mm256_set1_epi32(a) simde_mm256_set1_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_set1_epi64x (int64_t a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set1_epi64x(a); + #else + simde__m256i_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_set1_epi64x(a); + r_.m128i[1] = simde_mm_set1_epi64x(a); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set1_epi64x + #define _mm256_set1_epi64x(a) simde_mm256_set1_epi64x(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_set1_ps (simde_float32 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set1_ps(a); + #else + simde__m256_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_set1_ps(a); + r_.m128[1] = simde_mm_set1_ps(a); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set1_ps + #define _mm256_set1_ps(a) simde_mm256_set1_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_set1_pd (simde_float64 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_set1_pd(a); + #else + simde__m256d_private r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_set1_pd(a); + r_.m128d[1] = simde_mm_set1_pd(a); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_set1_pd + #define _mm256_set1_pd(a) simde_mm256_set1_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_deinterleaveeven_epi16 (simde__m256i a, simde__m256i b) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_x_mm_deinterleaveeven_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_x_mm_deinterleaveeven_epi16(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 32, a_.i16, b_.i16, 0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30); + #else + const size_t halfway_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 2; + const size_t quarter_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.i16[i] = a_.i16[2 * i]; + r_.i16[i + quarter_point] = b_.i16[2 * i]; + r_.i16[halfway_point + i] = a_.i16[halfway_point + 2 * i]; + r_.i16[halfway_point + i + quarter_point] = b_.i16[halfway_point + 2 * i]; + } + #endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_deinterleaveodd_epi16 (simde__m256i a, simde__m256i b) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_x_mm_deinterleaveodd_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_x_mm_deinterleaveodd_epi16(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 32, a_.i16, b_.i16, 1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31); + #else + const size_t halfway_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 2; + const size_t quarter_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.i16[i] = a_.i16[2 * i + 1]; + r_.i16[i + quarter_point] = b_.i16[2 * i + 1]; + r_.i16[halfway_point + i] = a_.i16[halfway_point + 2 * i + 1]; + r_.i16[halfway_point + i + quarter_point] = b_.i16[halfway_point + 2 * i + 1]; + } + #endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_deinterleaveeven_epi32 (simde__m256i a, simde__m256i b) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_x_mm_deinterleaveeven_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_x_mm_deinterleaveeven_epi32(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.i32, b_.i32, 0, 2, 8, 10, 4, 6, 12, 14); + #else + const size_t halfway_point = (sizeof(r_.i32) / sizeof(r_.i32[0])) / 2; + const size_t quarter_point = (sizeof(r_.i32) / sizeof(r_.i32[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.i32[i] = a_.i32[2 * i]; + r_.i32[i + quarter_point] = b_.i32[2 * i]; + r_.i32[halfway_point + i] = a_.i32[halfway_point + 2 * i]; + r_.i32[halfway_point + i + quarter_point] = b_.i32[halfway_point + 2 * i]; + } + #endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_deinterleaveodd_epi32 (simde__m256i a, simde__m256i b) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_x_mm_deinterleaveodd_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_x_mm_deinterleaveodd_epi32(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.i32, b_.i32, 1, 3, 9, 11, 5, 7, 13, 15); + #else + const size_t halfway_point = (sizeof(r_.i32) / sizeof(r_.i32[0])) / 2; + const size_t quarter_point = (sizeof(r_.i32) / sizeof(r_.i32[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.i32[i] = a_.i32[2 * i + 1]; + r_.i32[i + quarter_point] = b_.i32[2 * i + 1]; + r_.i32[halfway_point + i] = a_.i32[halfway_point + 2 * i + 1]; + r_.i32[halfway_point + i + quarter_point] = b_.i32[halfway_point + 2 * i + 1]; + } + #endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_deinterleaveeven_ps (simde__m256 a, simde__m256 b) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_x_mm_deinterleaveeven_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_x_mm_deinterleaveeven_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.f32, b_.f32, 0, 2, 8, 10, 4, 6, 12, 14); + #else + const size_t halfway_point = (sizeof(r_.f32) / sizeof(r_.f32[0])) / 2; + const size_t quarter_point = (sizeof(r_.f32) / sizeof(r_.f32[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.f32[i] = a_.f32[2 * i]; + r_.f32[i + quarter_point] = b_.f32[2 * i]; + r_.f32[halfway_point + i] = a_.f32[halfway_point + 2 * i]; + r_.f32[halfway_point + i + quarter_point] = b_.f32[halfway_point + 2 * i]; + } + #endif + + return simde__m256_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_deinterleaveodd_ps (simde__m256 a, simde__m256 b) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_x_mm_deinterleaveodd_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_x_mm_deinterleaveodd_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.f32, b_.f32, 1, 3, 9, 11, 5, 7, 13, 15); + #else + const size_t halfway_point = (sizeof(r_.f32) / sizeof(r_.f32[0])) / 2; + const size_t quarter_point = (sizeof(r_.f32) / sizeof(r_.f32[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.f32[i] = a_.f32[2 * i + 1]; + r_.f32[i + quarter_point] = b_.f32[2 * i + 1]; + r_.f32[halfway_point + i] = a_.f32[halfway_point + 2 * i + 1]; + r_.f32[halfway_point + i + quarter_point] = b_.f32[halfway_point + 2 * i + 1]; + } + #endif + + return simde__m256_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_deinterleaveeven_pd (simde__m256d a, simde__m256d b) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_x_mm_deinterleaveeven_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_x_mm_deinterleaveeven_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.f64, b_.f64, 0, 4, 2, 6); + #else + const size_t halfway_point = (sizeof(r_.f64) / sizeof(r_.f64[0])) / 2; + const size_t quarter_point = (sizeof(r_.f64) / sizeof(r_.f64[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.f64[i] = a_.f64[2 * i]; + r_.f64[i + quarter_point] = b_.f64[2 * i]; + r_.f64[halfway_point + i] = a_.f64[halfway_point + 2 * i]; + r_.f64[halfway_point + i + quarter_point] = b_.f64[halfway_point + 2 * i]; + } + #endif + + return simde__m256d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_deinterleaveodd_pd (simde__m256d a, simde__m256d b) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_x_mm_deinterleaveodd_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_x_mm_deinterleaveodd_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.f64, b_.f64, 1, 5, 3, 7); + #else + const size_t halfway_point = (sizeof(r_.f64) / sizeof(r_.f64[0])) / 2; + const size_t quarter_point = (sizeof(r_.f64) / sizeof(r_.f64[0])) / 4; + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.f64[i] = a_.f64[2 * i + 1]; + r_.f64[i + quarter_point] = b_.f64[2 * i + 1]; + r_.f64[halfway_point + i] = a_.f64[halfway_point + 2 * i + 1]; + r_.f64[halfway_point + i + quarter_point] = b_.f64[halfway_point + 2 * i + 1]; + } + #endif + + return simde__m256d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_abs_ps(simde__m256 a) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_fabsf(a_.f32[i]); + } + return simde__m256_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_abs_pd(simde__m256d a) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_fabs(a_.f64[i]); + } + return simde__m256d_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_add_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_add_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_add_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_add_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 + b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] + b_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_add_ps + #define _mm256_add_ps(a, b) simde_mm256_add_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_hadd_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_hadd_ps(a, b); + #else + return simde_mm256_add_ps(simde_x_mm256_deinterleaveeven_ps(a, b), simde_x_mm256_deinterleaveodd_ps(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_hadd_ps + #define _mm256_hadd_ps(a, b) simde_mm256_hadd_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_add_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_add_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_add_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_add_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 + b_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] + b_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_add_pd + #define _mm256_add_pd(a, b) simde_mm256_add_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_hadd_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_hadd_pd(a, b); + #else + return simde_mm256_add_pd(simde_x_mm256_deinterleaveeven_pd(a, b), simde_x_mm256_deinterleaveodd_pd(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_hadd_pd + #define _mm256_hadd_pd(a, b) simde_mm256_hadd_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_addsub_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_addsub_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_addsub_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_addsub_ps(a_.m128[1], b_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i += 2) { + r_.f32[ i ] = a_.f32[ i ] - b_.f32[ i ]; + r_.f32[i + 1] = a_.f32[i + 1] + b_.f32[i + 1]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_addsub_ps + #define _mm256_addsub_ps(a, b) simde_mm256_addsub_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_addsub_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_addsub_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_addsub_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_addsub_pd(a_.m128d[1], b_.m128d[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i += 2) { + r_.f64[ i ] = a_.f64[ i ] - b_.f64[ i ]; + r_.f64[i + 1] = a_.f64[i + 1] + b_.f64[i + 1]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_addsub_pd + #define _mm256_addsub_pd(a, b) simde_mm256_addsub_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_and_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_and_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_and_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_and_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] & b_.i32f[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_and_ps + #define _mm256_and_ps(a, b) simde_mm256_and_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_and_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_and_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_and_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_and_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] & b_.i32f[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_and_pd + #define _mm256_and_pd(a, b) simde_mm256_and_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_andnot_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_andnot_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_andnot_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_andnot_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~a_.i32f[i] & b_.i32f[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_andnot_ps + #define _mm256_andnot_ps(a, b) simde_mm256_andnot_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_andnot_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_andnot_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_andnot_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_andnot_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = ~a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~a_.i32f[i] & b_.i32f[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_andnot_pd + #define _mm256_andnot_pd(a, b) simde_mm256_andnot_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_blend_ps (simde__m256 a, simde__m256 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = ((imm8 >> i) & 1) ? b_.f32[i] : a_.f32[i]; + } + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_blend_ps(a, b, imm8) _mm256_blend_ps(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_blend_ps(a, b, imm8) \ + simde_mm256_set_m128( \ + simde_mm_blend_ps(simde_mm256_extractf128_ps(a, 1), simde_mm256_extractf128_ps(b, 1), (imm8) >> 4), \ + simde_mm_blend_ps(simde_mm256_extractf128_ps(a, 0), simde_mm256_extractf128_ps(b, 0), (imm8) & 0x0F)) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_blend_ps + #define _mm256_blend_ps(a, b, imm8) simde_mm256_blend_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_blend_pd (simde__m256d a, simde__m256d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = ((imm8 >> i) & 1) ? b_.f64[i] : a_.f64[i]; + } + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_blend_pd(a, b, imm8) _mm256_blend_pd(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_blend_pd(a, b, imm8) \ + simde_mm256_set_m128d( \ + simde_mm_blend_pd(simde_mm256_extractf128_pd(a, 1), simde_mm256_extractf128_pd(b, 1), (imm8) >> 2), \ + simde_mm_blend_pd(simde_mm256_extractf128_pd(a, 0), simde_mm256_extractf128_pd(b, 0), (imm8) & 3)) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_blend_pd + #define _mm256_blend_pd(a, b, imm8) simde_mm256_blend_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_blendv_ps (simde__m256 a, simde__m256 b, simde__m256 mask) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_blendv_ps(a, b, mask); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b), + mask_ = simde__m256_to_private(mask); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_blendv_ps(a_.m128[0], b_.m128[0], mask_.m128[0]); + r_.m128[1] = simde_mm_blendv_ps(a_.m128[1], b_.m128[1], mask_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.f32[i] = (mask_.u32[i] & (UINT32_C(1) << 31)) ? b_.f32[i] : a_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_blendv_ps + #define _mm256_blendv_ps(a, b, imm8) simde_mm256_blendv_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_blendv_pd (simde__m256d a, simde__m256d b, simde__m256d mask) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_blendv_pd(a, b, mask); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b), + mask_ = simde__m256d_to_private(mask); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_blendv_pd(a_.m128d[0], b_.m128d[0], mask_.m128d[0]); + r_.m128d[1] = simde_mm_blendv_pd(a_.m128d[1], b_.m128d[1], mask_.m128d[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.f64[i] = (mask_.u64[i] & (UINT64_C(1) << 63)) ? b_.f64[i] : a_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_blendv_pd + #define _mm256_blendv_pd(a, b, imm8) simde_mm256_blendv_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_broadcast_pd (simde__m128d const * mem_addr) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_broadcast_pd(mem_addr); + #else + simde__m256d_private r_; + + simde__m128d tmp = simde_mm_loadu_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, mem_addr)); + r_.m128d[0] = tmp; + r_.m128d[1] = tmp; + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcast_pd + #define _mm256_broadcast_pd(mem_addr) simde_mm256_broadcast_pd(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_broadcast_ps (simde__m128 const * mem_addr) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_broadcast_ps(mem_addr); + #else + simde__m256_private r_; + + simde__m128 tmp = simde_mm_loadu_ps(HEDLEY_REINTERPRET_CAST(simde_float32 const*, mem_addr)); + r_.m128[0] = tmp; + r_.m128[1] = tmp; + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcast_ps + #define _mm256_broadcast_ps(mem_addr) simde_mm256_broadcast_ps(HEDLEY_REINTERPRET_CAST(simde__m128 const*, mem_addr)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_broadcast_sd (simde_float64 const * a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_broadcast_sd(a); + #else + return simde_mm256_set1_pd(*a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcast_sd + #define _mm256_broadcast_sd(mem_addr) simde_mm256_broadcast_sd(HEDLEY_REINTERPRET_CAST(double const*, mem_addr)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_broadcast_ss (simde_float32 const * a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_broadcast_ss(a); + #else + return simde_mm_set1_ps(*a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcast_ss + #define _mm_broadcast_ss(mem_addr) simde_mm_broadcast_ss(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_broadcast_ss (simde_float32 const * a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_broadcast_ss(a); + #else + return simde_mm256_set1_ps(*a); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcast_ss + #define _mm256_broadcast_ss(mem_addr) simde_mm256_broadcast_ss(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_castpd128_pd256 (simde__m128d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castpd128_pd256(a); + #else + simde__m256d_private r_; + simde__m128d_private a_ = simde__m128d_to_private(a); + + r_.m128d_private[0] = a_; + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castpd128_pd256 + #define _mm256_castpd128_pd256(a) simde_mm256_castpd128_pd256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm256_castpd256_pd128 (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castpd256_pd128(a); + #else + simde__m256d_private a_ = simde__m256d_to_private(a); + return a_.m128d[0]; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castpd256_pd128 + #define _mm256_castpd256_pd128(a) simde_mm256_castpd256_pd128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_castps128_ps256 (simde__m128 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castps128_ps256(a); + #else + simde__m256_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + r_.m128_private[0] = a_; + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castps128_ps256 + #define _mm256_castps128_ps256(a) simde_mm256_castps128_ps256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm256_castps256_ps128 (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castps256_ps128(a); + #else + simde__m256_private a_ = simde__m256_to_private(a); + return a_.m128[0]; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castps256_ps128 + #define _mm256_castps256_ps128(a) simde_mm256_castps256_ps128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_castsi128_si256 (simde__m128i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castsi128_si256(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + r_.m128i_private[0] = a_; + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castsi128_si256 + #define _mm256_castsi128_si256(a) simde_mm256_castsi128_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_castsi256_si128 (simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_castsi256_si128(a); + #else + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.m128i[0]; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_castsi256_si128 + #define _mm256_castsi256_si128(a) simde_mm256_castsi256_si128(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_round_ps (simde__m256 a, const int rounding) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + switch (rounding & ~SIMDE_MM_FROUND_NO_EXC) { + #if defined(simde_math_nearbyintf) + case SIMDE_MM_FROUND_CUR_DIRECTION: + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_nearbyintf(a_.f32[i]); + } + break; + #endif + + #if defined(simde_math_roundf) + case SIMDE_MM_FROUND_TO_NEAREST_INT: + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_roundf(a_.f32[i]); + } + break; + #endif + + #if defined(simde_math_floorf) + case SIMDE_MM_FROUND_TO_NEG_INF: + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_floorf(a_.f32[i]); + } + break; + #endif + + #if defined(simde_math_ceilf) + case SIMDE_MM_FROUND_TO_POS_INF: + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_ceilf(a_.f32[i]); + } + break; + #endif + + #if defined(simde_math_truncf) + case SIMDE_MM_FROUND_TO_ZERO: + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_truncf(a_.f32[i]); + } + break; + #endif + + default: + HEDLEY_UNREACHABLE_RETURN(simde_mm256_undefined_ps()); + } + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_round_ps(a, rounding) _mm256_round_ps(a, rounding) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_round_ps + #define _mm256_round_ps(a, rounding) simde_mm256_round_ps(a, rounding) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_round_pd (simde__m256d a, const int rounding) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + switch (rounding & ~SIMDE_MM_FROUND_NO_EXC) { + #if defined(simde_math_nearbyint) + case SIMDE_MM_FROUND_CUR_DIRECTION: + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_nearbyint(a_.f64[i]); + } + break; + #endif + + #if defined(simde_math_round) + case SIMDE_MM_FROUND_TO_NEAREST_INT: + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_round(a_.f64[i]); + } + break; + #endif + + #if defined(simde_math_floor) + case SIMDE_MM_FROUND_TO_NEG_INF: + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_floor(a_.f64[i]); + } + break; + #endif + + #if defined(simde_math_ceil) + case SIMDE_MM_FROUND_TO_POS_INF: + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_ceil(a_.f64[i]); + } + break; + #endif + + #if defined(simde_math_trunc) + case SIMDE_MM_FROUND_TO_ZERO: + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_trunc(a_.f64[i]); + } + break; + #endif + + default: + HEDLEY_UNREACHABLE_RETURN(simde_mm256_undefined_pd()); + } + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_round_pd(a, rounding) _mm256_round_pd(a, rounding) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_round_pd + #define _mm256_round_pd(a, rounding) simde_mm256_round_pd(a, rounding) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_ceil_pd (simde__m256d a) { + return simde_mm256_round_pd(a, SIMDE_MM_FROUND_TO_POS_INF); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_ceil_pd + #define _mm256_ceil_pd(a) simde_mm256_ceil_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_ceil_ps (simde__m256 a) { + return simde_mm256_round_ps(a, SIMDE_MM_FROUND_TO_POS_INF); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_ceil_ps + #define _mm256_ceil_ps(a) simde_mm256_ceil_ps(a) +#endif + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DIAGNOSTIC_DISABLE_FLOAT_EQUAL + +/* This implementation does not support signaling NaNs (yet?) */ +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmp_pd (simde__m128d a, simde__m128d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 31) { + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + case SIMDE_CMP_EQ_UQ: + case SIMDE_CMP_EQ_OS: + case SIMDE_CMP_EQ_US: + return simde_mm_cmpeq_pd(a, b); + break; + case SIMDE_CMP_LT_OS: + case SIMDE_CMP_NGE_US: + case SIMDE_CMP_LT_OQ: + case SIMDE_CMP_NGE_UQ: + return simde_mm_cmplt_pd(a, b); + break; + case SIMDE_CMP_LE_OS: + case SIMDE_CMP_NGT_US: + case SIMDE_CMP_LE_OQ: + case SIMDE_CMP_NGT_UQ: + return simde_mm_cmple_pd(a, b); + break; + case SIMDE_CMP_NEQ_UQ: + case SIMDE_CMP_NEQ_OQ: + case SIMDE_CMP_NEQ_US: + case SIMDE_CMP_NEQ_OS: + return simde_mm_cmpneq_pd(a, b); + break; + case SIMDE_CMP_NLT_US: + case SIMDE_CMP_GE_OS: + case SIMDE_CMP_NLT_UQ: + case SIMDE_CMP_GE_OQ: + return simde_mm_cmpge_pd(a, b); + break; + case SIMDE_CMP_NLE_US: + case SIMDE_CMP_GT_OS: + case SIMDE_CMP_NLE_UQ: + case SIMDE_CMP_GT_OQ: + return simde_mm_cmpgt_pd(a, b); + break; + case SIMDE_CMP_FALSE_OQ: + case SIMDE_CMP_FALSE_OS: + return simde_mm_setzero_pd(); + break; + case SIMDE_CMP_TRUE_UQ: + case SIMDE_CMP_TRUE_US: + return simde_x_mm_setone_pd(); + break; + case SIMDE_CMP_UNORD_Q: + case SIMDE_CMP_UNORD_S: + return simde_mm_cmpunord_pd(a, b); + break; + case SIMDE_CMP_ORD_Q: + case SIMDE_CMP_ORD_S: + return simde_mm_cmpord_pd(a, b); + break; + } + + HEDLEY_UNREACHABLE_RETURN(simde_mm_setzero_pd()); +} +#if defined(SIMDE_X86_AVX_NATIVE) && (!defined(__clang__) || !defined(__AVX512F__)) +# define simde_mm_cmp_pd(a, b, imm8) _mm_cmp_pd(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_cmp_pd + #define _mm_cmp_pd(a, b, imm8) simde_mm_cmp_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmp_ps (simde__m128 a, simde__m128 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 31) { + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + case SIMDE_CMP_EQ_UQ: + case SIMDE_CMP_EQ_OS: + case SIMDE_CMP_EQ_US: + return simde_mm_cmpeq_ps(a, b); + break; + case SIMDE_CMP_LT_OS: + case SIMDE_CMP_NGE_US: + case SIMDE_CMP_LT_OQ: + case SIMDE_CMP_NGE_UQ: + return simde_mm_cmplt_ps(a, b); + break; + case SIMDE_CMP_LE_OS: + case SIMDE_CMP_NGT_US: + case SIMDE_CMP_LE_OQ: + case SIMDE_CMP_NGT_UQ: + return simde_mm_cmple_ps(a, b); + break; + case SIMDE_CMP_NEQ_UQ: + case SIMDE_CMP_NEQ_OQ: + case SIMDE_CMP_NEQ_US: + case SIMDE_CMP_NEQ_OS: + return simde_mm_cmpneq_ps(a, b); + break; + case SIMDE_CMP_NLT_US: + case SIMDE_CMP_GE_OS: + case SIMDE_CMP_NLT_UQ: + case SIMDE_CMP_GE_OQ: + return simde_mm_cmpge_ps(a, b); + break; + case SIMDE_CMP_NLE_US: + case SIMDE_CMP_GT_OS: + case SIMDE_CMP_NLE_UQ: + case SIMDE_CMP_GT_OQ: + return simde_mm_cmpgt_ps(a, b); + break; + case SIMDE_CMP_FALSE_OQ: + case SIMDE_CMP_FALSE_OS: + return simde_mm_setzero_ps(); + break; + case SIMDE_CMP_TRUE_UQ: + case SIMDE_CMP_TRUE_US: + return simde_x_mm_setone_ps(); + break; + case SIMDE_CMP_UNORD_Q: + case SIMDE_CMP_UNORD_S: + return simde_mm_cmpunord_ps(a, b); + break; + case SIMDE_CMP_ORD_Q: + case SIMDE_CMP_ORD_S: + return simde_mm_cmpord_ps(a, b); + break; + } + + HEDLEY_UNREACHABLE_RETURN(simde_mm_setzero_ps()); +} +/* Prior to 9.0 clang has problems with _mm{,256}_cmp_{ps,pd} for all four of the true/false + comparisons, but only when AVX-512 is enabled. __FILE_NAME__ was added in 9.0, so that's + what we use to check for clang 9 since the version macros are unreliable. */ +#if defined(SIMDE_X86_AVX_NATIVE) && (!defined(__clang__) || !defined(__AVX512F__)) +# define simde_mm_cmp_ps(a, b, imm8) _mm_cmp_ps(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_cmp_ps + #define _mm_cmp_ps(a, b, imm8) simde_mm_cmp_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_cmp_sd (simde__m128d a, simde__m128d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 31) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + r_.u64[0] = (a_.f64[0] == b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LT_OS: + r_.u64[0] = (a_.f64[0] < b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LE_OS: + r_.u64[0] = (a_.f64[0] <= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_UNORD_Q: +#if defined(simde_math_isnan) + r_.u64[0] = (simde_math_isnan(a_.f64[0]) || simde_math_isnan(b_.f64[0])) ? ~UINT64_C(0) : UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_UQ: + r_.u64[0] = (a_.f64[0] != b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLT_US: + r_.u64[0] = (a_.f64[0] >= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLE_US: + r_.u64[0] = (a_.f64[0] > b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_ORD_Q: +#if defined(simde_math_isnan) + r_.u64[0] = (!simde_math_isnan(a_.f64[0]) && !simde_math_isnan(b_.f64[0])) ? ~UINT64_C(0) : UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_UQ: + r_.u64[0] = (a_.f64[0] == b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGE_US: + r_.u64[0] = (a_.f64[0] < b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGT_US: + r_.u64[0] = (a_.f64[0] <= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_FALSE_OQ: + r_.u64[0] = UINT64_C(0); + break; + case SIMDE_CMP_NEQ_OQ: + r_.u64[0] = (a_.f64[0] != b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GE_OS: + r_.u64[0] = (a_.f64[0] >= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GT_OS: + r_.u64[0] = (a_.f64[0] > b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_TRUE_UQ: + r_.u64[0] = ~UINT64_C(0); + break; + case SIMDE_CMP_EQ_OS: + r_.u64[0] = (a_.f64[0] == b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LT_OQ: + r_.u64[0] = (a_.f64[0] < b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LE_OQ: + r_.u64[0] = (a_.f64[0] <= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_UNORD_S: +#if defined(simde_math_isnan) + r_.u64[0] = (simde_math_isnan(a_.f64[0]) || simde_math_isnan(b_.f64[0])) ? ~UINT64_C(0) : UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_US: + r_.u64[0] = (a_.f64[0] != b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLT_UQ: + r_.u64[0] = (a_.f64[0] >= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLE_UQ: + r_.u64[0] = (a_.f64[0] > b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_ORD_S: +#if defined(simde_math_isnan) + r_.u64[0] = (simde_math_isnan(a_.f64[0]) || simde_math_isnan(b_.f64[0])) ? UINT64_C(0) : ~UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_US: + r_.u64[0] = (a_.f64[0] == b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGE_UQ: + r_.u64[0] = (a_.f64[0] < b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGT_UQ: + r_.u64[0] = (a_.f64[0] <= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_FALSE_OS: + r_.u64[0] = UINT64_C(0); + break; + case SIMDE_CMP_NEQ_OS: + r_.u64[0] = (a_.f64[0] != b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GE_OQ: + r_.u64[0] = (a_.f64[0] >= b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GT_OQ: + r_.u64[0] = (a_.f64[0] > b_.f64[0]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_TRUE_US: + r_.u64[0] = ~UINT64_C(0); + break; + } + r_.u64[1] = a_.u64[1]; + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm_cmp_sd(a, b, imm8) _mm_cmp_sd(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_cmp_sd + #define _mm_cmp_sd(a, b, imm8) simde_mm_cmp_sd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_cmp_ss (simde__m128 a, simde__m128 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 31) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + r_.u32[0] = (a_.f32[0] == b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LT_OS: + r_.u32[0] = (a_.f32[0] < b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LE_OS: + r_.u32[0] = (a_.f32[0] <= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_UNORD_Q: +#if defined(simde_math_isnanf) + r_.u32[0] = (simde_math_isnanf(a_.f32[0]) || simde_math_isnanf(b_.f32[0])) ? ~UINT32_C(0) : UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_UQ: + r_.u32[0] = (a_.f32[0] != b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLT_US: + r_.u32[0] = (a_.f32[0] >= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLE_US: + r_.u32[0] = (a_.f32[0] > b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_ORD_Q: +#if defined(simde_math_isnanf) + r_.u32[0] = (!simde_math_isnanf(a_.f32[0]) && !simde_math_isnanf(b_.f32[0])) ? ~UINT32_C(0) : UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_UQ: + r_.u32[0] = (a_.f32[0] == b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGE_US: + r_.u32[0] = (a_.f32[0] < b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGT_US: + r_.u32[0] = (a_.f32[0] <= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_FALSE_OQ: + r_.u32[0] = UINT32_C(0); + break; + case SIMDE_CMP_NEQ_OQ: + r_.u32[0] = (a_.f32[0] != b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GE_OS: + r_.u32[0] = (a_.f32[0] >= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GT_OS: + r_.u32[0] = (a_.f32[0] > b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_TRUE_UQ: + r_.u32[0] = ~UINT32_C(0); + break; + case SIMDE_CMP_EQ_OS: + r_.u32[0] = (a_.f32[0] == b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LT_OQ: + r_.u32[0] = (a_.f32[0] < b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LE_OQ: + r_.u32[0] = (a_.f32[0] <= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_UNORD_S: +#if defined(simde_math_isnanf) + r_.u32[0] = (simde_math_isnanf(a_.f32[0]) || simde_math_isnanf(b_.f32[0])) ? ~UINT32_C(0) : UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_US: + r_.u32[0] = (a_.f32[0] != b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLT_UQ: + r_.u32[0] = (a_.f32[0] >= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLE_UQ: + r_.u32[0] = (a_.f32[0] > b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_ORD_S: +#if defined(simde_math_isnanf) + r_.u32[0] = (simde_math_isnanf(a_.f32[0]) || simde_math_isnanf(b_.f32[0])) ? UINT32_C(0) : ~UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_US: + r_.u32[0] = (a_.f32[0] == b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGE_UQ: + r_.u32[0] = (a_.f32[0] < b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGT_UQ: + r_.u32[0] = (a_.f32[0] <= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_FALSE_OS: + r_.u32[0] = UINT32_C(0); + break; + case SIMDE_CMP_NEQ_OS: + r_.u32[0] = (a_.f32[0] != b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GE_OQ: + r_.u32[0] = (a_.f32[0] >= b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GT_OQ: + r_.u32[0] = (a_.f32[0] > b_.f32[0]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_TRUE_US: + r_.u32[0] = ~UINT32_C(0); + break; + } + r_.u32[1] = a_.u32[1]; + r_.u32[2] = a_.u32[2]; + r_.u32[3] = a_.u32[3]; + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm_cmp_ss(a, b, imm8) _mm_cmp_ss(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_cmp_ss + #define _mm_cmp_ss(a, b, imm8) simde_mm_cmp_ss(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_cmp_pd (simde__m256d a, simde__m256d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 31) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + +#if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 == b_.f64)); + break; + case SIMDE_CMP_LT_OS: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 < b_.f64)); + break; + case SIMDE_CMP_LE_OS: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 <= b_.f64)); + break; + case SIMDE_CMP_UNORD_Q: +#if defined(simde_math_isnan) + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_UQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 != b_.f64)); + break; + case SIMDE_CMP_NLT_US: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 >= b_.f64)); + break; + case SIMDE_CMP_NLE_US: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 > b_.f64)); + break; + case SIMDE_CMP_ORD_Q: +#if defined(simde_math_isnan) + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (!simde_math_isnan(a_.f64[i]) && !simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_UQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 == b_.f64)); + break; + case SIMDE_CMP_NGE_US: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 < b_.f64)); + break; + case SIMDE_CMP_NGT_US: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 <= b_.f64)); + break; + case SIMDE_CMP_FALSE_OQ: + r_ = simde__m256d_to_private(simde_mm256_setzero_pd()); + break; + case SIMDE_CMP_NEQ_OQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 != b_.f64)); + break; + case SIMDE_CMP_GE_OS: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 >= b_.f64)); + break; + case SIMDE_CMP_GT_OS: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 > b_.f64)); + break; + case SIMDE_CMP_TRUE_UQ: + r_ = simde__m256d_to_private(simde_x_mm256_setone_pd()); + break; + case SIMDE_CMP_EQ_OS: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 == b_.f64)); + break; + case SIMDE_CMP_LT_OQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 < b_.f64)); + break; + case SIMDE_CMP_LE_OQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 <= b_.f64)); + break; + case SIMDE_CMP_UNORD_S: +#if defined(simde_math_isnan) + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_US: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 != b_.f64)); + break; + case SIMDE_CMP_NLT_UQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 >= b_.f64)); + break; + case SIMDE_CMP_NLE_UQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 > b_.f64)); + break; + case SIMDE_CMP_ORD_S: +#if defined(simde_math_isnan) + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? UINT64_C(0) : ~UINT64_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_US: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 == b_.f64)); + break; + case SIMDE_CMP_NGE_UQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 < b_.f64)); + break; + case SIMDE_CMP_NGT_UQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 <= b_.f64)); + break; + case SIMDE_CMP_FALSE_OS: + r_ = simde__m256d_to_private(simde_mm256_setzero_pd()); + break; + case SIMDE_CMP_NEQ_OS: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 != b_.f64)); + break; + case SIMDE_CMP_GE_OQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 >= b_.f64)); + break; + case SIMDE_CMP_GT_OQ: + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), (a_.f64 > b_.f64)); + break; + case SIMDE_CMP_TRUE_US: + r_ = simde__m256d_to_private(simde_x_mm256_setone_pd()); + break; + default: + HEDLEY_UNREACHABLE(); + break; + } +#else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + r_.u64[i] = (a_.f64[i] == b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LT_OS: + r_.u64[i] = (a_.f64[i] < b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LE_OS: + r_.u64[i] = (a_.f64[i] <= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_UNORD_Q: + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NEQ_UQ: + r_.u64[i] = (a_.f64[i] != b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLT_US: + r_.u64[i] = (a_.f64[i] >= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLE_US: + r_.u64[i] = (a_.f64[i] > b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_ORD_Q: +#if defined(simde_math_isnan) + r_.u64[i] = (!simde_math_isnan(a_.f64[i]) && !simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_UQ: + r_.u64[i] = (a_.f64[i] == b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGE_US: + r_.u64[i] = (a_.f64[i] < b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGT_US: + r_.u64[i] = (a_.f64[i] <= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_FALSE_OQ: + r_.u64[i] = UINT64_C(0); + break; + case SIMDE_CMP_NEQ_OQ: + r_.u64[i] = (a_.f64[i] != b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GE_OS: + r_.u64[i] = (a_.f64[i] >= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GT_OS: + r_.u64[i] = (a_.f64[i] > b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_TRUE_UQ: + r_.u64[i] = ~UINT64_C(0); + break; + case SIMDE_CMP_EQ_OS: + r_.u64[i] = (a_.f64[i] == b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LT_OQ: + r_.u64[i] = (a_.f64[i] < b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_LE_OQ: + r_.u64[i] = (a_.f64[i] <= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_UNORD_S: +#if defined(simde_math_isnan) + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? ~UINT64_C(0) : UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_US: + r_.u64[i] = (a_.f64[i] != b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLT_UQ: + r_.u64[i] = (a_.f64[i] >= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NLE_UQ: + r_.u64[i] = (a_.f64[i] > b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_ORD_S: +#if defined(simde_math_isnan) + r_.u64[i] = (simde_math_isnan(a_.f64[i]) || simde_math_isnan(b_.f64[i])) ? UINT64_C(0) : ~UINT64_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_US: + r_.u64[i] = (a_.f64[i] == b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGE_UQ: + r_.u64[i] = (a_.f64[i] < b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_NGT_UQ: + r_.u64[i] = (a_.f64[i] <= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_FALSE_OS: + r_.u64[i] = UINT64_C(0); + break; + case SIMDE_CMP_NEQ_OS: + r_.u64[i] = (a_.f64[i] != b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GE_OQ: + r_.u64[i] = (a_.f64[i] >= b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_GT_OQ: + r_.u64[i] = (a_.f64[i] > b_.f64[i]) ? ~UINT64_C(0) : UINT64_C(0); + break; + case SIMDE_CMP_TRUE_US: + r_.u64[i] = ~UINT64_C(0); + break; + default: + HEDLEY_UNREACHABLE(); + break; + } + } +#endif + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) && (!defined(__clang__) || !defined(__AVX512F__)) +# define simde_mm256_cmp_pd(a, b, imm8) _mm256_cmp_pd(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmp_pd + #define _mm256_cmp_pd(a, b, imm8) simde_mm256_cmp_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_cmp_ps (simde__m256 a, simde__m256 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 31) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + +#if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 == b_.f32)); + break; + case SIMDE_CMP_LT_OS: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 < b_.f32)); + break; + case SIMDE_CMP_LE_OS: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 <= b_.f32)); + break; + case SIMDE_CMP_UNORD_Q: +#if defined(simde_math_isnanf) + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_UQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 != b_.f32)); + break; + case SIMDE_CMP_NLT_US: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 >= b_.f32)); + break; + case SIMDE_CMP_NLE_US: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 > b_.f32)); + break; + case SIMDE_CMP_ORD_Q: +#if defined(simde_math_isnanf) + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (!simde_math_isnanf(a_.f32[i]) && !simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_UQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 == b_.f32)); + break; + case SIMDE_CMP_NGE_US: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 < b_.f32)); + break; + case SIMDE_CMP_NGT_US: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 <= b_.f32)); + break; + case SIMDE_CMP_FALSE_OQ: + r_ = simde__m256_to_private(simde_mm256_setzero_ps()); + break; + case SIMDE_CMP_NEQ_OQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 != b_.f32)); + break; + case SIMDE_CMP_GE_OS: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 >= b_.f32)); + break; + case SIMDE_CMP_GT_OS: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 > b_.f32)); + break; + case SIMDE_CMP_TRUE_UQ: + r_ = simde__m256_to_private(simde_x_mm256_setone_ps()); + break; + case SIMDE_CMP_EQ_OS: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 == b_.f32)); + break; + case SIMDE_CMP_LT_OQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 < b_.f32)); + break; + case SIMDE_CMP_LE_OQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 <= b_.f32)); + break; + case SIMDE_CMP_UNORD_S: +#if defined(simde_math_isnanf) + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_US: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 != b_.f32)); + break; + case SIMDE_CMP_NLT_UQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 >= b_.f32)); + break; + case SIMDE_CMP_NLE_UQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 > b_.f32)); + break; + case SIMDE_CMP_ORD_S: +#if defined(simde_math_isnanf) + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? UINT32_C(0) : ~UINT32_C(0); + } +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_US: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 == b_.f32)); + break; + case SIMDE_CMP_NGE_UQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 < b_.f32)); + break; + case SIMDE_CMP_NGT_UQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 <= b_.f32)); + break; + case SIMDE_CMP_FALSE_OS: + r_ = simde__m256_to_private(simde_mm256_setzero_ps()); + break; + case SIMDE_CMP_NEQ_OS: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 != b_.f32)); + break; + case SIMDE_CMP_GE_OQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 >= b_.f32)); + break; + case SIMDE_CMP_GT_OQ: + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), (a_.f32 > b_.f32)); + break; + case SIMDE_CMP_TRUE_US: + r_ = simde__m256_to_private(simde_x_mm256_setone_ps()); + break; + default: + HEDLEY_UNREACHABLE(); + break; + } +#else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + switch (imm8) { + case SIMDE_CMP_EQ_OQ: + r_.u32[i] = (a_.f32[i] == b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LT_OS: + r_.u32[i] = (a_.f32[i] < b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LE_OS: + r_.u32[i] = (a_.f32[i] <= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_UNORD_Q: +#if defined(simde_math_isnanf) + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_UQ: + r_.u32[i] = (a_.f32[i] != b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLT_US: + r_.u32[i] = (a_.f32[i] >= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLE_US: + r_.u32[i] = (a_.f32[i] > b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_ORD_Q: +#if defined(simde_math_isnanf) + r_.u32[i] = (!simde_math_isnanf(a_.f32[i]) && !simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_UQ: + r_.u32[i] = (a_.f32[i] == b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGE_US: + r_.u32[i] = (a_.f32[i] < b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGT_US: + r_.u32[i] = (a_.f32[i] <= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_FALSE_OQ: + r_.u32[i] = UINT32_C(0); + break; + case SIMDE_CMP_NEQ_OQ: + r_.u32[i] = (a_.f32[i] != b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GE_OS: + r_.u32[i] = (a_.f32[i] >= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GT_OS: + r_.u32[i] = (a_.f32[i] > b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_TRUE_UQ: + r_.u32[i] = ~UINT32_C(0); + break; + case SIMDE_CMP_EQ_OS: + r_.u32[i] = (a_.f32[i] == b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LT_OQ: + r_.u32[i] = (a_.f32[i] < b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_LE_OQ: + r_.u32[i] = (a_.f32[i] <= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_UNORD_S: +#if defined(simde_math_isnanf) + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? ~UINT32_C(0) : UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_NEQ_US: + r_.u32[i] = (a_.f32[i] != b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLT_UQ: + r_.u32[i] = (a_.f32[i] >= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NLE_UQ: + r_.u32[i] = (a_.f32[i] > b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_ORD_S: +#if defined(simde_math_isnanf) + r_.u32[i] = (simde_math_isnanf(a_.f32[i]) || simde_math_isnanf(b_.f32[i])) ? UINT32_C(0) : ~UINT32_C(0); +#else + HEDLEY_UNREACHABLE(); +#endif + break; + case SIMDE_CMP_EQ_US: + r_.u32[i] = (a_.f32[i] == b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGE_UQ: + r_.u32[i] = (a_.f32[i] < b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_NGT_UQ: + r_.u32[i] = (a_.f32[i] <= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_FALSE_OS: + r_.u32[i] = UINT32_C(0); + break; + case SIMDE_CMP_NEQ_OS: + r_.u32[i] = (a_.f32[i] != b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GE_OQ: + r_.u32[i] = (a_.f32[i] >= b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_GT_OQ: + r_.u32[i] = (a_.f32[i] > b_.f32[i]) ? ~UINT32_C(0) : UINT32_C(0); + break; + case SIMDE_CMP_TRUE_US: + r_.u32[i] = ~UINT32_C(0); + break; + default: + HEDLEY_UNREACHABLE(); + break; + } + } +#endif + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) && (!defined(__clang__) || !defined(__AVX512F__)) +# define simde_mm256_cmp_ps(a, b, imm8) _mm256_cmp_ps(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmp_ps + #define _mm256_cmp_ps(a, b, imm8) simde_mm256_cmp_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_copysign_ps(simde__m256 dest, simde__m256 src) { + simde__m256_private + r_, + dest_ = simde__m256_to_private(dest), + src_ = simde__m256_to_private(src); + + #if defined(simde_math_copysignf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_copysignf(dest_.f32[i], src_.f32[i]); + } + #else + simde__m256 sgnbit = simde_mm256_xor_ps(simde_mm256_set1_ps(SIMDE_FLOAT32_C(0.0)), simde_mm256_set1_ps(-SIMDE_FLOAT32_C(0.0))); + return simde_mm256_xor_ps(simde_mm256_and_ps(sgnbit, src), simde_mm256_andnot_ps(sgnbit, dest)); + #endif + + return simde__m256_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_copysign_pd(simde__m256d dest, simde__m256d src) { + simde__m256d_private + r_, + dest_ = simde__m256d_to_private(dest), + src_ = simde__m256d_to_private(src); + + #if defined(simde_math_copysign) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_copysign(dest_.f64[i], src_.f64[i]); + } + #else + simde__m256d sgnbit = simde_mm256_xor_pd(simde_mm256_set1_pd(SIMDE_FLOAT64_C(0.0)), simde_mm256_set1_pd(-SIMDE_FLOAT64_C(0.0))); + return simde_mm256_xor_pd(simde_mm256_and_pd(sgnbit, src), simde_mm256_andnot_pd(sgnbit, dest)); + #endif + + return simde__m256d_from_private(r_); +} + +HEDLEY_DIAGNOSTIC_POP /* -Wfloat-equal */ + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_cvtepi32_pd (simde__m128i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvtepi32_pd(a); + #else + simde__m256d_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = HEDLEY_STATIC_CAST(simde_float64, a_.i32[i]); + } + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi32_pd + #define _mm256_cvtepi32_pd(a) simde_mm256_cvtepi32_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 + simde_mm256_cvtepi32_ps (simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvtepi32_ps(a); + #else + simde__m256_private r_; + simde__m256i_private a_ = simde__m256i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = HEDLEY_STATIC_CAST(simde_float32, a_.i32[i]); + } + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi32_ps + #define _mm256_cvtepi32_ps(a) simde_mm256_cvtepi32_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_cvtpd_epi32 (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvtpd_epi32(a); + #else + simde__m128i_private r_; + simde__m256d_private a_ = simde__m256d_to_private(a); + + #if defined(simde_math_nearbyint) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f64) / sizeof(a_.f64[0])) ; i++) { + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, simde_math_nearbyint(a_.f64[i])); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtpd_epi32 + #define _mm256_cvtpd_epi32(a) simde_mm256_cvtpd_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm256_cvtpd_ps (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvtpd_ps(a); + #else + simde__m128_private r_; + simde__m256d_private a_ = simde__m256d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = HEDLEY_STATIC_CAST(simde_float32, a_.f64[i]); + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtpd_ps + #define _mm256_cvtpd_ps(a) simde_mm256_cvtpd_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtps_epi32 (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvtps_epi32(a); + #else + simde__m256i_private r_; + simde__m256_private a_ = simde__m256_to_private(a); + + #if defined(simde_math_nearbyintf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, simde_math_nearbyintf(a_.f32[i])); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtps_epi32 + #define _mm256_cvtps_epi32(a) simde_mm256_cvtps_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_cvtps_pd (simde__m128 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvtps_pd(a); + #else + simde__m256d_private r_; + simde__m128_private a_ = simde__m128_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + r_.f64[i] = HEDLEY_STATIC_CAST(double, a_.f32[i]); + } + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtps_pd + #define _mm256_cvtps_pd(a) simde_mm256_cvtps_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde_float64 +simde_mm256_cvtsd_f64 (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,9,0) || \ + HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MSVC_VERSION_CHECK(19,14,0)) + return _mm256_cvtsd_f64(a); + #else + simde__m256d_private a_ = simde__m256d_to_private(a); + return a_.f64[0]; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtsd_f64 + #define _mm256_cvtsd_f64(a) simde_mm256_cvtsd_f64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm256_cvtsi256_si32 (simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,9,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MSVC_VERSION_CHECK(19,14,0)) + return _mm256_cvtsi256_si32(a); + #else + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.i32[0]; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtsi256_si32 + #define _mm256_cvtsi256_si32(a) simde_mm256_cvtsi256_si32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde_float32 +simde_mm256_cvtss_f32 (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) && ( \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,9,0) || \ + HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + HEDLEY_MSVC_VERSION_CHECK(19,14,0)) + return _mm256_cvtss_f32(a); + #else + simde__m256_private a_ = simde__m256_to_private(a); + return a_.f32[0]; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtss_f32 + #define _mm256_cvtss_f32(a) simde_mm256_cvtss_f32(a) +#endif + + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_cvttpd_epi32 (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvttpd_epi32(a); + #else + simde__m128i_private r_; + simde__m256d_private a_ = simde__m256d_to_private(a); + + #if defined(simde_math_trunc) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f64) / sizeof(a_.f64[0])) ; i++) { + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, simde_math_trunc(a_.f64[i])); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvttpd_epi32 + #define _mm256_cvttpd_epi32(a) simde_mm256_cvttpd_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvttps_epi32 (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_cvttps_epi32(a); + #else + simde__m256i_private r_; + simde__m256_private a_ = simde__m256_to_private(a); + + #if defined(simde_math_truncf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + r_.i32[i] = SIMDE_CONVERT_FTOI(int32_t, simde_math_truncf(a_.f32[i])); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvttps_epi32 + #define _mm256_cvttps_epi32(a) simde_mm256_cvttps_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_div_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_div_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_div_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_div_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 / b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] / b_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_div_ps + #define _mm256_div_ps(a, b) simde_mm256_div_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_div_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_div_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_div_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_div_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 / b_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] / b_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_div_pd + #define _mm256_div_pd(a, b) simde_mm256_div_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm256_extractf128_pd (simde__m256d a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256d_private a_ = simde__m256d_to_private(a); + return a_.m128d[imm8]; +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_extractf128_pd(a, imm8) _mm256_extractf128_pd(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_extractf128_pd + #define _mm256_extractf128_pd(a, imm8) simde_mm256_extractf128_pd(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm256_extractf128_ps (simde__m256 a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256_private a_ = simde__m256_to_private(a); + return a_.m128[imm8]; +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_extractf128_ps(a, imm8) _mm256_extractf128_ps(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_extractf128_ps + #define _mm256_extractf128_ps(a, imm8) simde_mm256_extractf128_ps(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_extractf128_si256 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.m128i[imm8]; +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_extractf128_si256(a, imm8) _mm256_extractf128_si256(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_extractf128_si256 + #define _mm256_extractf128_si256(a, imm8) simde_mm256_extractf128_si256(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_floor_pd (simde__m256d a) { + return simde_mm256_round_pd(a, SIMDE_MM_FROUND_TO_NEG_INF); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_floor_pd + #define _mm256_floor_pd(a) simde_mm256_floor_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_floor_ps (simde__m256 a) { + return simde_mm256_round_ps(a, SIMDE_MM_FROUND_TO_NEG_INF); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_floor_ps + #define _mm256_floor_ps(a) simde_mm256_floor_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_insert_epi8 (simde__m256i a, int8_t i, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 31) { + simde__m256i_private a_ = simde__m256i_to_private(a); + + a_.i8[index] = i; + + return simde__m256i_from_private(a_); +} +#if defined(SIMDE_X86_AVX_NATIVE) + #define simde_mm256_insert_epi8(a, i, index) _mm256_insert_epi8(a, i, index) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_insert_epi8 + #define _mm256_insert_epi8(a, i, index) simde_mm256_insert_epi8(a, i, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_insert_epi16 (simde__m256i a, int16_t i, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 15) { + simde__m256i_private a_ = simde__m256i_to_private(a); + + a_.i16[index] = i; + + return simde__m256i_from_private(a_); +} +#if defined(SIMDE_X86_AVX_NATIVE) + #define simde_mm256_insert_epi16(a, i, index) _mm256_insert_epi16(a, i, index) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_insert_epi16 + #define _mm256_insert_epi16(a, i, imm8) simde_mm256_insert_epi16(a, i, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_insert_epi32 (simde__m256i a, int32_t i, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 7) { + simde__m256i_private a_ = simde__m256i_to_private(a); + + a_.i32[index] = i; + + return simde__m256i_from_private(a_); +} +#if defined(SIMDE_X86_AVX_NATIVE) + #define simde_mm256_insert_epi32(a, i, index) _mm256_insert_epi32(a, i, index) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_insert_epi32 + #define _mm256_insert_epi32(a, i, index) simde_mm256_insert_epi32(a, i, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_insert_epi64 (simde__m256i a, int64_t i, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 3) { + simde__m256i_private a_ = simde__m256i_to_private(a); + + a_.i64[index] = i; + + return simde__m256i_from_private(a_); +} +#if defined(SIMDE_X86_AVX_NATIVE) && defined(SIMDE_ARCH_AMD64) && \ + (!defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19,20,0)) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,7,0) + #define simde_mm256_insert_epi64(a, i, index) _mm256_insert_epi64(a, i, index) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #undef _mm256_insert_epi64 + #define _mm256_insert_epi64(a, i, index) simde_mm256_insert_epi64(a, i, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d simde_mm256_insertf128_pd(simde__m256d a, simde__m128d b, int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256d_private a_ = simde__m256d_to_private(a); + simde__m128d_private b_ = simde__m128d_to_private(b); + + a_.m128d_private[imm8] = b_; + + return simde__m256d_from_private(a_); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_insertf128_pd + #define _mm256_insertf128_pd(a, b, imm8) simde_mm256_insertf128_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 simde_mm256_insertf128_ps(simde__m256 a, simde__m128 b, int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256_private a_ = simde__m256_to_private(a); + simde__m128_private b_ = simde__m128_to_private(b); + + a_.m128_private[imm8] = b_; + + return simde__m256_from_private(a_); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_insertf128_ps + #define _mm256_insertf128_ps(a, b, imm8) simde_mm256_insertf128_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i simde_mm256_insertf128_si256(simde__m256i a, simde__m128i b, int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256i_private a_ = simde__m256i_to_private(a); + simde__m128i_private b_ = simde__m128i_to_private(b); + + a_.m128i_private[imm8] = b_; + + return simde__m256i_from_private(a_); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_insertf128_si256 + #define _mm256_insertf128_si256(a, b, imm8) simde_mm256_insertf128_si256(a, b, imm8) +#endif + +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_dp_ps(a, b, imm8) _mm256_dp_ps(a, b, imm8) +#else +# define simde_mm256_dp_ps(a, b, imm8) \ + simde_mm256_set_m128( \ + simde_mm_dp_ps(simde_mm256_extractf128_ps(a, 1), simde_mm256_extractf128_ps(b, 1), imm8), \ + simde_mm_dp_ps(simde_mm256_extractf128_ps(a, 0), simde_mm256_extractf128_ps(b, 0), imm8)) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_dp_ps + #define _mm256_dp_ps(a, b, imm8) simde_mm256_dp_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm256_extract_epi32 (simde__m256i a, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 7) { + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.i32[index]; +} +#if defined(SIMDE_X86_AVX_NATIVE) + #define simde_mm256_extract_epi32(a, index) _mm256_extract_epi32(a, index) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_extract_epi32 + #define _mm256_extract_epi32(a, index) simde_mm256_extract_epi32(a, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int64_t +simde_mm256_extract_epi64 (simde__m256i a, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 3) { + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.i64[index]; +} +#if defined(SIMDE_X86_AVX_NATIVE) && defined(SIMDE_ARCH_AMD64) + #if !defined(HEDLEY_MSVC_VERSION) || HEDLEY_MSVC_VERSION_CHECK(19,20,0) + #define simde_mm256_extract_epi64(a, index) _mm256_extract_epi64(a, index) + #endif +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && !defined(SIMDE_ARCH_AMD64)) + #undef _mm256_extract_epi64 + #define _mm256_extract_epi64(a, index) simde_mm256_extract_epi64(a, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_lddqu_si256 (simde__m256i const * mem_addr) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_si256(mem_addr); + #else + simde__m256i r; + simde_memcpy(&r, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256i), sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_lddqu_si256 + #define _mm256_lddqu_si256(a) simde_mm256_lddqu_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_load_pd (const double mem_addr[HEDLEY_ARRAY_PARAM(4)]) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_load_pd(mem_addr); + #else + simde__m256d r; + simde_memcpy(&r, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256d), sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_load_pd + #define _mm256_load_pd(a) simde_mm256_load_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_load_ps (const float mem_addr[HEDLEY_ARRAY_PARAM(8)]) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_load_ps(mem_addr); + #else + simde__m256 r; + simde_memcpy(&r, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256), sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_load_ps + #define _mm256_load_ps(a) simde_mm256_load_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_load_si256 (simde__m256i const * mem_addr) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_load_si256(mem_addr); + #else + simde__m256i r; + simde_memcpy(&r, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256i), sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_load_si256 + #define _mm256_load_si256(a) simde_mm256_load_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_loadu_pd (const double a[HEDLEY_ARRAY_PARAM(4)]) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_pd(a); + #else + simde__m256d r; + simde_memcpy(&r, a, sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_loadu_pd + #define _mm256_loadu_pd(a) simde_mm256_loadu_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_loadu_ps (const float a[HEDLEY_ARRAY_PARAM(8)]) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_ps(a); + #else + simde__m256 r; + simde_memcpy(&r, a, sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_loadu_ps + #define _mm256_loadu_ps(a) simde_mm256_loadu_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_loadu_epi8(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm256_loadu_epi8(mem_addr); + #elif defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr)); + #else + simde__m256i r; + simde_memcpy(&r, mem_addr, sizeof(r)); + return r; + #endif +} +#define simde_x_mm256_loadu_epi8(mem_addr) simde_mm256_loadu_epi8(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm256_loadu_epi8 + #define _mm256_loadu_epi8(a) simde_mm256_loadu_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_loadu_epi16(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm256_loadu_epi16(mem_addr); + #elif defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr)); + #else + simde__m256i r; + simde_memcpy(&r, mem_addr, sizeof(r)); + return r; + #endif +} +#define simde_x_mm256_loadu_epi16(mem_addr) simde_mm256_loadu_epi16(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm256_loadu_epi16 + #define _mm256_loadu_epi16(a) simde_mm256_loadu_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_loadu_epi32(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm256_loadu_epi32(mem_addr); + #elif defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr)); + #else + simde__m256i r; + simde_memcpy(&r, mem_addr, sizeof(r)); + return r; + #endif +} +#define simde_x_mm256_loadu_epi32(mem_addr) simde_mm256_loadu_epi32(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm256_loadu_epi32 + #define _mm256_loadu_epi32(a) simde_mm256_loadu_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_loadu_epi64(void const * mem_addr) { + #if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483) && !defined(SIMDE_BUG_CLANG_REV_344862) + return _mm256_loadu_epi64(mem_addr); + #elif defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr)); + #else + simde__m256i r; + simde_memcpy(&r, mem_addr, sizeof(r)); + return r; + #endif +} +#define simde_x_mm256_loadu_epi64(mem_addr) simde_mm256_loadu_epi64(mem_addr) +#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && (defined(SIMDE_BUG_GCC_95483) || defined(SIMDE_BUG_CLANG_REV_344862))) + #undef _mm256_loadu_epi64 + #define _mm256_loadu_epi64(a) simde_mm256_loadu_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_loadu_si256 (void const * mem_addr) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_loadu_si256(SIMDE_ALIGN_CAST(const __m256i*, mem_addr)); + #else + simde__m256i r; + simde_memcpy(&r, mem_addr, sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_loadu_si256 + #define _mm256_loadu_si256(mem_addr) simde_mm256_loadu_si256(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_loadu2_m128 (const float hiaddr[HEDLEY_ARRAY_PARAM(4)], const float loaddr[HEDLEY_ARRAY_PARAM(4)]) { + #if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_BUG_GCC_91341) && !defined(SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS) + return _mm256_loadu2_m128(hiaddr, loaddr); + #else + return + simde_mm256_insertf128_ps(simde_mm256_castps128_ps256(simde_mm_loadu_ps(loaddr)), + simde_mm_loadu_ps(hiaddr), 1); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_loadu2_m128 + #define _mm256_loadu2_m128(hiaddr, loaddr) simde_mm256_loadu2_m128(hiaddr, loaddr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_loadu2_m128d (const double hiaddr[HEDLEY_ARRAY_PARAM(2)], const double loaddr[HEDLEY_ARRAY_PARAM(2)]) { + #if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_BUG_GCC_91341) && !defined(SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS) + return _mm256_loadu2_m128d(hiaddr, loaddr); + #else + return + simde_mm256_insertf128_pd(simde_mm256_castpd128_pd256(simde_mm_loadu_pd(loaddr)), + simde_mm_loadu_pd(hiaddr), 1); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_loadu2_m128d + #define _mm256_loadu2_m128d(hiaddr, loaddr) simde_mm256_loadu2_m128d(hiaddr, loaddr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_loadu2_m128i (const simde__m128i* hiaddr, const simde__m128i* loaddr) { + #if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_BUG_GCC_91341) && !defined(SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS) + return _mm256_loadu2_m128i(hiaddr, loaddr); + #else + return + simde_mm256_insertf128_si256(simde_mm256_castsi128_si256(simde_mm_loadu_si128(loaddr)), + simde_mm_loadu_si128(hiaddr), 1); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_loadu2_m128i + #define _mm256_loadu2_m128i(hiaddr, loaddr) simde_mm256_loadu2_m128i(hiaddr, loaddr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_maskload_pd (const simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m128i mask) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_maskload_pd(mem_addr, mask); + #else + simde__m128d_private + mem_ = simde__m128d_to_private(simde_mm_loadu_pd(mem_addr)), + r_; + simde__m128i_private mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vandq_s64(mem_.neon_i64, vshrq_n_s64(mask_.neon_i64, 63)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.i64[i] = mem_.i64[i] & (mask_.i64[i] >> 63); + } + #endif + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_maskload_pd + #define _mm_maskload_pd(mem_addr, mask) simde_mm_maskload_pd(HEDLEY_REINTERPRET_CAST(double const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_maskload_pd (const simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m256i mask) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_maskload_pd(mem_addr, mask); + #else + simde__m256d_private r_; + simde__m256i_private mask_ = simde__m256i_to_private(mask); + + r_ = simde__m256d_to_private(simde_mm256_loadu_pd(mem_addr)); + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.i64[i] &= mask_.i64[i] >> 63; + } + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskload_pd + #define _mm256_maskload_pd(mem_addr, mask) simde_mm256_maskload_pd(HEDLEY_REINTERPRET_CAST(double const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_maskload_ps (const simde_float32 mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m128i mask) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_maskload_ps(mem_addr, mask); + #else + simde__m128_private + mem_ = simde__m128_to_private(simde_mm_loadu_ps(mem_addr)), + r_; + simde__m128i_private mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vandq_s32(mem_.neon_i32, vshrq_n_s32(mask_.neon_i32, 31)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = mem_.i32[i] & (mask_.i32[i] >> 31); + } + #endif + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_maskload_ps + #define _mm_maskload_ps(mem_addr, mask) simde_mm_maskload_ps(HEDLEY_REINTERPRET_CAST(float const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_maskload_ps (const simde_float32 mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m256i mask) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_maskload_ps(mem_addr, mask); + #else + simde__m256_private r_; + simde__m256i_private mask_ = simde__m256i_to_private(mask); + + r_ = simde__m256_to_private(simde_mm256_loadu_ps(mem_addr)); + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.i32[i] &= mask_.i32[i] >> 31; + } + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskload_ps + #define _mm256_maskload_ps(mem_addr, mask) simde_mm256_maskload_ps(HEDLEY_REINTERPRET_CAST(float const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_maskstore_pd (simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(2)], simde__m128i mask, simde__m128d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm_maskstore_pd(mem_addr, mask, a); + #else + simde__m128i_private mask_ = simde__m128i_to_private(mask); + simde__m128d_private a_ = simde__m128d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f64) / sizeof(a_.f64[0])) ; i++) { + if (mask_.u64[i] >> 63) + mem_addr[i] = a_.f64[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_maskstore_pd + #define _mm_maskstore_pd(mem_addr, mask, a) simde_mm_maskstore_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_maskstore_pd (simde_float64 mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m256i mask, simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_maskstore_pd(mem_addr, mask, a); + #else + simde__m256i_private mask_ = simde__m256i_to_private(mask); + simde__m256d_private a_ = simde__m256d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f64) / sizeof(a_.f64[0])) ; i++) { + if (mask_.u64[i] & (UINT64_C(1) << 63)) + mem_addr[i] = a_.f64[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskstore_pd + #define _mm256_maskstore_pd(mem_addr, mask, a) simde_mm256_maskstore_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_maskstore_ps (simde_float32 mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m128i mask, simde__m128 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm_maskstore_ps(mem_addr, mask, a); + #else + simde__m128i_private mask_ = simde__m128i_to_private(mask); + simde__m128_private a_ = simde__m128_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + if (mask_.u32[i] & (UINT32_C(1) << 31)) + mem_addr[i] = a_.f32[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_maskstore_ps + #define _mm_maskstore_ps(mem_addr, mask, a) simde_mm_maskstore_ps(HEDLEY_REINTERPRET_CAST(float*, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_maskstore_ps (simde_float32 mem_addr[HEDLEY_ARRAY_PARAM(8)], simde__m256i mask, simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_maskstore_ps(mem_addr, mask, a); + #else + simde__m256i_private mask_ = simde__m256i_to_private(mask); + simde__m256_private a_ = simde__m256_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + if (mask_.u32[i] & (UINT32_C(1) << 31)) + mem_addr[i] = a_.f32[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskstore_ps + #define _mm256_maskstore_ps(mem_addr, mask, a) simde_mm256_maskstore_ps(HEDLEY_REINTERPRET_CAST(float*, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_min_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_min_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_min_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_min_ps(a_.m128[1], b_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (a_.f32[i] < b_.f32[i]) ? a_.f32[i] : b_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_ps + #define _mm256_min_ps(a, b) simde_mm256_min_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_min_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_min_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_min_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_min_pd(a_.m128d[1], b_.m128d[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = (a_.f64[i] < b_.f64[i]) ? a_.f64[i] : b_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_pd + #define _mm256_min_pd(a, b) simde_mm256_min_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_max_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_max_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_max_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_max_ps(a_.m128[1], b_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = (a_.f32[i] > b_.f32[i]) ? a_.f32[i] : b_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_ps + #define _mm256_max_ps(a, b) simde_mm256_max_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_max_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_max_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_max_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_max_pd(a_.m128d[1], b_.m128d[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = (a_.f64[i] > b_.f64[i]) ? a_.f64[i] : b_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_pd + #define _mm256_max_pd(a, b) simde_mm256_max_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_movedup_pd (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_movedup_pd(a); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.f64, a_.f64, 0, 0, 2, 2); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i += 2) { + r_.f64[i] = r_.f64[i + 1] = a_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_movedup_pd + #define _mm256_movedup_pd(a) simde_mm256_movedup_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_movehdup_ps (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_movehdup_ps(a); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.f32, a_.f32, 1, 1, 3, 3, 5, 5, 7, 7); + #else + SIMDE_VECTORIZE + for (size_t i = 1 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i += 2) { + r_.f32[i - 1] = r_.f32[i] = a_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_movehdup_ps + #define _mm256_movehdup_ps(a) simde_mm256_movehdup_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_moveldup_ps (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_moveldup_ps(a); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.f32, a_.f32, 0, 0, 2, 2, 4, 4, 6, 6); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i += 2) { + r_.f32[i] = r_.f32[i + 1] = a_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_moveldup_ps + #define _mm256_moveldup_ps(a) simde_mm256_moveldup_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_movemask_ps (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_movemask_ps(a); + #else + simde__m256_private a_ = simde__m256_to_private(a); + int r = 0; + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.f32) / sizeof(a_.f32[0])) ; i++) { + r |= (a_.u32[i] >> 31) << i; + } + + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_movemask_ps + #define _mm256_movemask_ps(a) simde_mm256_movemask_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_movemask_pd (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_movemask_pd(a); + #else + simde__m256d_private a_ = simde__m256d_to_private(a); + int r = 0; + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.f64) / sizeof(a_.f64[0])) ; i++) { + r |= (a_.u64[i] >> 63) << i; + } + + return r; + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_movemask_pd + #define _mm256_movemask_pd(a) simde_mm256_movemask_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_mul_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_mul_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_mul_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_mul_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 * b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] * b_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_mul_ps + #define _mm256_mul_ps(a, b) simde_mm256_mul_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_mul_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_mul_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_mul_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_mul_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 * b_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] * b_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_mul_pd + #define _mm256_mul_pd(a, b) simde_mm256_mul_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_or_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_or_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_or_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_or_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f | b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] | b_.u32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_or_ps + #define _mm256_or_ps(a, b) simde_mm256_or_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_or_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_or_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_or_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_or_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f | b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = a_.u64[i] | b_.u64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_or_pd + #define _mm256_or_pd(a, b) simde_mm256_or_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_permute_ps (simde__m256 a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.m128_private[i >> 2].f32[(imm8 >> ((i << 1) & 7)) & 3]; + } + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_permute_ps(a, imm8) _mm256_permute_ps(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute_ps + #define _mm256_permute_ps(a, imm8) simde_mm256_permute_ps(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_permute_pd (simde__m256d a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[((imm8 >> i) & 1) + (i & 2)]; + } + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_permute_pd(a, imm8) _mm256_permute_pd(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute_pd + #define _mm256_permute_pd(a, imm8) simde_mm256_permute_pd(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_permute_ps (simde__m128 a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[(imm8 >> ((i << 1) & 7)) & 3]; + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm_permute_ps(a, imm8) _mm_permute_ps(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_permute_ps + #define _mm_permute_ps(a, imm8) simde_mm_permute_ps(a, imm8) +#endif + + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_permute_pd (simde__m128d a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 3) { + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[((imm8 >> i) & 1) + (i & 2)]; + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm_permute_pd(a, imm8) _mm_permute_pd(a, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_permute_pd + #define _mm_permute_pd(a, imm8) simde_mm_permute_pd(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_permutevar_ps (simde__m128 a, simde__m128i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_permutevar_ps(a, b); + #else + simde__m128_private + r_, + a_ = simde__m128_to_private(a); + simde__m128i_private b_ = simde__m128i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[b_.i32[i] & 3]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_permutevar_ps + #define _mm_permutevar_ps(a, b) simde_mm_permutevar_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_permutevar_pd (simde__m128d a, simde__m128i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_permutevar_pd(a, b); + #else + simde__m128d_private + r_, + a_ = simde__m128d_to_private(a); + simde__m128i_private b_ = simde__m128i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[(b_.i64[i] & 2) >> 1]; + } + + return simde__m128d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_permutevar_pd + #define _mm_permutevar_pd(a, b) simde_mm_permutevar_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_permutevar_ps (simde__m256 a, simde__m256i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_permutevar_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + simde__m256i_private b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[(b_.i32[i] & 3) + (i & 4)]; + } + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permutevar_ps + #define _mm256_permutevar_ps(a, b) simde_mm256_permutevar_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_permutevar_pd (simde__m256d a, simde__m256i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_permutevar_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + simde__m256i_private b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[((b_.i64[i] & 2) >> 1) + (i & 2)]; + } + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permutevar_pd + #define _mm256_permutevar_pd(a, b) simde_mm256_permutevar_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_permute2f128_ps (simde__m256 a, simde__m256 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + r_.m128_private[0] = (imm8 & 0x08) ? simde__m128_to_private(simde_mm_setzero_ps()) : ((imm8 & 0x02) ? b_.m128_private[(imm8 ) & 1] : a_.m128_private[(imm8 ) & 1]); + r_.m128_private[1] = (imm8 & 0x80) ? simde__m128_to_private(simde_mm_setzero_ps()) : ((imm8 & 0x20) ? b_.m128_private[(imm8 >> 4) & 1] : a_.m128_private[(imm8 >> 4) & 1]); + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_permute2f128_ps(a, b, imm8) _mm256_permute2f128_ps(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute2f128_ps + #define _mm256_permute2f128_ps(a, b, imm8) simde_mm256_permute2f128_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_permute2f128_pd (simde__m256d a, simde__m256d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + r_.m128d_private[0] = (imm8 & 0x08) ? simde__m128d_to_private(simde_mm_setzero_pd()) : ((imm8 & 0x02) ? b_.m128d_private[(imm8 ) & 1] : a_.m128d_private[(imm8 ) & 1]); + r_.m128d_private[1] = (imm8 & 0x80) ? simde__m128d_to_private(simde_mm_setzero_pd()) : ((imm8 & 0x20) ? b_.m128d_private[(imm8 >> 4) & 1] : a_.m128d_private[(imm8 >> 4) & 1]); + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_permute2f128_pd(a, b, imm8) _mm256_permute2f128_pd(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute2f128_pd + #define _mm256_permute2f128_pd(a, b, imm8) simde_mm256_permute2f128_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_permute2f128_si256 (simde__m256i a, simde__m256i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + r_.m128i_private[0] = (imm8 & 0x08) ? simde__m128i_to_private(simde_mm_setzero_si128()) : ((imm8 & 0x02) ? b_.m128i_private[(imm8 ) & 1] : a_.m128i_private[(imm8 ) & 1]); + r_.m128i_private[1] = (imm8 & 0x80) ? simde__m128i_to_private(simde_mm_setzero_si128()) : ((imm8 & 0x20) ? b_.m128i_private[(imm8 >> 4) & 1] : a_.m128i_private[(imm8 >> 4) & 1]); + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) +# define simde_mm256_permute2f128_si128(a, b, imm8) _mm256_permute2f128_si128(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute2f128_si256 + #define _mm256_permute2f128_si256(a, b, imm8) simde_mm256_permute2f128_si256(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_rcp_ps (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_rcp_ps(a); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_rcp_ps(a_.m128[0]); + r_.m128[1] = simde_mm_rcp_ps(a_.m128[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = SIMDE_FLOAT32_C(1.0) / a_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_rcp_ps + #define _mm256_rcp_ps(a) simde_mm256_rcp_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_rsqrt_ps (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_rsqrt_ps(a); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if defined(simde_math_sqrtf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = 1.0f / simde_math_sqrtf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_rsqrt_ps + #define _mm256_rsqrt_ps(a) simde_mm256_rsqrt_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_setr_epi8 ( + int8_t e31, int8_t e30, int8_t e29, int8_t e28, int8_t e27, int8_t e26, int8_t e25, int8_t e24, + int8_t e23, int8_t e22, int8_t e21, int8_t e20, int8_t e19, int8_t e18, int8_t e17, int8_t e16, + int8_t e15, int8_t e14, int8_t e13, int8_t e12, int8_t e11, int8_t e10, int8_t e9, int8_t e8, + int8_t e7, int8_t e6, int8_t e5, int8_t e4, int8_t e3, int8_t e2, int8_t e1, int8_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setr_epi8( + e31, e30, e29, e28, e27, e26, e25, e24, + e23, e22, e21, e20, e19, e18, e17, e16, + e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm256_set_epi8( + e0, e1, e2, e3, e4, e5, e6, e7, + e8, e9, e10, e11, e12, e13, e14, e15, + e16, e17, e18, e19, e20, e21, e22, e23, + e24, e25, e26, e27, e28, e29, e30, e31); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_epi8 + #define _mm256_setr_epi8(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_setr_epi8(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_setr_epi16 ( + int16_t e15, int16_t e14, int16_t e13, int16_t e12, int16_t e11, int16_t e10, int16_t e9, int16_t e8, + int16_t e7, int16_t e6, int16_t e5, int16_t e4, int16_t e3, int16_t e2, int16_t e1, int16_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setr_epi16( + e15, e14, e13, e12, e11, e10, e9, e8, + e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm256_set_epi16( + e0, e1, e2, e3, e4, e5, e6, e7, + e8, e9, e10, e11, e12, e13, e14, e15); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_epi16 + #define _mm256_setr_epi16(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_setr_epi16(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_setr_epi32 ( + int32_t e7, int32_t e6, int32_t e5, int32_t e4, int32_t e3, int32_t e2, int32_t e1, int32_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setr_epi32(e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm256_set_epi32(e0, e1, e2, e3, e4, e5, e6, e7); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_epi32 + #define _mm256_setr_epi32(e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_setr_epi32(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_setr_epi64x (int64_t e3, int64_t e2, int64_t e1, int64_t e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setr_epi64x(e3, e2, e1, e0); + #else + return simde_mm256_set_epi64x(e0, e1, e2, e3); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_epi64x + #define _mm256_setr_epi64x(e3, e2, e1, e0) \ + simde_mm256_setr_epi64x(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_setr_ps ( + simde_float32 e7, simde_float32 e6, simde_float32 e5, simde_float32 e4, + simde_float32 e3, simde_float32 e2, simde_float32 e1, simde_float32 e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setr_ps(e7, e6, e5, e4, e3, e2, e1, e0); + #else + return simde_mm256_set_ps(e0, e1, e2, e3, e4, e5, e6, e7); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_ps + #define _mm256_setr_ps(e7, e6, e5, e4, e3, e2, e1, e0) \ + simde_mm256_setr_ps(e7, e6, e5, e4, e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_setr_pd (simde_float64 e3, simde_float64 e2, simde_float64 e1, simde_float64 e0) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_setr_pd(e3, e2, e1, e0); + #else + return simde_mm256_set_pd(e0, e1, e2, e3); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_pd + #define _mm256_setr_pd(e3, e2, e1, e0) \ + simde_mm256_setr_pd(e3, e2, e1, e0) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_setr_m128 (simde__m128 lo, simde__m128 hi) { + #if defined(SIMDE_X86_AVX_NATIVE) && \ + !defined(SIMDE_BUG_GCC_REV_247851) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,6,0) + return _mm256_setr_m128(lo, hi); + #else + return simde_mm256_set_m128(hi, lo); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_m128 + #define _mm256_setr_m128(lo, hi) \ + simde_mm256_setr_m128(lo, hi) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_setr_m128d (simde__m128d lo, simde__m128d hi) { + #if defined(SIMDE_X86_AVX_NATIVE) && \ + !defined(SIMDE_BUG_GCC_REV_247851) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,6,0) + return _mm256_setr_m128d(lo, hi); + #else + return simde_mm256_set_m128d(hi, lo); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_m128d + #define _mm256_setr_m128d(lo, hi) \ + simde_mm256_setr_m128d(lo, hi) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_setr_m128i (simde__m128i lo, simde__m128i hi) { + #if defined(SIMDE_X86_AVX_NATIVE) && \ + !defined(SIMDE_BUG_GCC_REV_247851) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,6,0) + return _mm256_setr_m128i(lo, hi); + #else + return simde_mm256_set_m128i(hi, lo); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_setr_m128i + #define _mm256_setr_m128i(lo, hi) \ + simde_mm256_setr_m128i(lo, hi) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_shuffle_ps (simde__m256 a, simde__m256 b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + r_.f32[0] = a_.m128_private[0].f32[(imm8 >> 0) & 3]; + r_.f32[1] = a_.m128_private[0].f32[(imm8 >> 2) & 3]; + r_.f32[2] = b_.m128_private[0].f32[(imm8 >> 4) & 3]; + r_.f32[3] = b_.m128_private[0].f32[(imm8 >> 6) & 3]; + r_.f32[4] = a_.m128_private[1].f32[(imm8 >> 0) & 3]; + r_.f32[5] = a_.m128_private[1].f32[(imm8 >> 2) & 3]; + r_.f32[6] = b_.m128_private[1].f32[(imm8 >> 4) & 3]; + r_.f32[7] = b_.m128_private[1].f32[(imm8 >> 6) & 3]; + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) + #define simde_mm256_shuffle_ps(a, b, imm8) _mm256_shuffle_ps(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) + #define simde_mm256_shuffle_ps(a, b, imm8) \ + simde_mm256_set_m128( \ + simde_mm_shuffle_ps(simde_mm256_extractf128_ps(a, 1), simde_mm256_extractf128_ps(b, 1), (imm8)), \ + simde_mm_shuffle_ps(simde_mm256_extractf128_ps(a, 0), simde_mm256_extractf128_ps(b, 0), (imm8))) +#elif defined(SIMDE_SHUFFLE_VECTOR_) + #define simde_mm256_shuffle_ps(a, b, imm8) \ + SIMDE_SHUFFLE_VECTOR_(32, 32, a, b, \ + (((imm8) >> 0) & 3) + 0, \ + (((imm8) >> 2) & 3) + 0, \ + (((imm8) >> 4) & 3) + 8, \ + (((imm8) >> 6) & 3) + 8, \ + (((imm8) >> 0) & 3) + 4, \ + (((imm8) >> 2) & 3) + 4, \ + (((imm8) >> 4) & 3) + 12, \ + (((imm8) >> 6) & 3) + 12) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_shuffle_ps + #define _mm256_shuffle_ps(a, b, imm8) simde_mm256_shuffle_ps(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_shuffle_pd (simde__m256d a, simde__m256d b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + r_.f64[0] = a_.f64[((imm8 ) & 1) ]; + r_.f64[1] = b_.f64[((imm8 >> 1) & 1) ]; + r_.f64[2] = a_.f64[((imm8 >> 2) & 1) | 2]; + r_.f64[3] = b_.f64[((imm8 >> 3) & 1) | 2]; + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_NATIVE) + #define simde_mm256_shuffle_pd(a, b, imm8) _mm256_shuffle_pd(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) + #define simde_mm256_shuffle_pd(a, b, imm8) \ + simde_mm256_set_m128d( \ + simde_mm_shuffle_pd(simde_mm256_extractf128_pd(a, 1), simde_mm256_extractf128_pd(b, 1), (imm8 >> 0) & 3), \ + simde_mm_shuffle_pd(simde_mm256_extractf128_pd(a, 0), simde_mm256_extractf128_pd(b, 0), (imm8 >> 2) & 3)) +#elif defined(SIMDE_SHUFFLE_VECTOR_) + #define simde_mm256_shuffle_pd(a, b, imm8) \ + SIMDE_SHUFFLE_VECTOR_(64, 32, a, b, \ + (((imm8) >> 0) & 1) + 0, \ + (((imm8) >> 1) & 1) + 4, \ + (((imm8) >> 2) & 1) + 2, \ + (((imm8) >> 3) & 1) + 6) +#endif +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_shuffle_pd + #define _mm256_shuffle_pd(a, b, imm8) simde_mm256_shuffle_pd(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_sqrt_ps (simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_sqrt_ps(a); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_sqrt_ps(a_.m128[0]); + r_.m128[1] = simde_mm_sqrt_ps(a_.m128[1]); + #elif defined(simde_math_sqrtf) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = simde_math_sqrtf(a_.f32[i]); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_sqrt_ps + #define _mm256_sqrt_ps(a) simde_mm256_sqrt_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_sqrt_pd (simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_sqrt_pd(a); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_sqrt_pd(a_.m128d[0]); + r_.m128d[1] = simde_mm_sqrt_pd(a_.m128d[1]); + #elif defined(simde_math_sqrt) + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = simde_math_sqrt(a_.f64[i]); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_sqrt_pd + #define _mm256_sqrt_pd(a) simde_mm256_sqrt_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_store_ps (simde_float32 mem_addr[8], simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_store_ps(mem_addr, a); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_store_ps + #define _mm256_store_ps(mem_addr, a) simde_mm256_store_ps(HEDLEY_REINTERPRET_CAST(float*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_store_pd (simde_float64 mem_addr[4], simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_store_pd(mem_addr, a); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256d), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_store_pd + #define _mm256_store_pd(mem_addr, a) simde_mm256_store_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_store_si256 (simde__m256i* mem_addr, simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_store_si256(mem_addr, a); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256i), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_store_si256 + #define _mm256_store_si256(mem_addr, a) simde_mm256_store_si256(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_storeu_ps (simde_float32 mem_addr[8], simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_storeu_ps(mem_addr, a); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_storeu_ps + #define _mm256_storeu_ps(mem_addr, a) simde_mm256_storeu_ps(HEDLEY_REINTERPRET_CAST(float*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_storeu_pd (simde_float64 mem_addr[4], simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_storeu_pd(mem_addr, a); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_storeu_pd + #define _mm256_storeu_pd(mem_addr, a) simde_mm256_storeu_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_storeu_si256 (void* mem_addr, simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_storeu_si256(SIMDE_ALIGN_CAST(__m256i*, mem_addr), a); + #else + simde_memcpy(mem_addr, &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_storeu_si256 + #define _mm256_storeu_si256(mem_addr, a) simde_mm256_storeu_si256(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_storeu2_m128 (simde_float32 hi_addr[4], simde_float32 lo_addr[4], simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_BUG_GCC_91341) && !defined(SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS) + _mm256_storeu2_m128(hi_addr, lo_addr, a); + #else + simde_mm_storeu_ps(lo_addr, simde_mm256_castps256_ps128(a)); + simde_mm_storeu_ps(hi_addr, simde_mm256_extractf128_ps(a, 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_storeu2_m128 + #define _mm256_storeu2_m128(hi_addr, lo_addr, a) simde_mm256_storeu2_m128(hi_addr, lo_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_storeu2_m128d (simde_float64 hi_addr[2], simde_float64 lo_addr[2], simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_BUG_GCC_91341) && !defined(SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS) + _mm256_storeu2_m128d(hi_addr, lo_addr, a); + #else + simde_mm_storeu_pd(lo_addr, simde_mm256_castpd256_pd128(a)); + simde_mm_storeu_pd(hi_addr, simde_mm256_extractf128_pd(a, 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_storeu2_m128d + #define _mm256_storeu2_m128d(hi_addr, lo_addr, a) simde_mm256_storeu2_m128d(hi_addr, lo_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_storeu2_m128i (simde__m128i* hi_addr, simde__m128i* lo_addr, simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) && !defined(SIMDE_BUG_GCC_91341) && !defined(SIMDE_BUG_MCST_LCC_MISSING_AVX_LOAD_STORE_M128_FUNCS) + _mm256_storeu2_m128i(hi_addr, lo_addr, a); + #else + simde_mm_storeu_si128(lo_addr, simde_mm256_castsi256_si128(a)); + simde_mm_storeu_si128(hi_addr, simde_mm256_extractf128_si256(a, 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_storeu2_m128i + #define _mm256_storeu2_m128i(hi_addr, lo_addr, a) simde_mm256_storeu2_m128i(hi_addr, lo_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_stream_ps (simde_float32 mem_addr[8], simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_stream_ps(mem_addr, a); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_stream_ps + #define _mm256_stream_ps(mem_addr, a) simde_mm256_stream_ps(HEDLEY_REINTERPRET_CAST(float*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_stream_pd (simde_float64 mem_addr[4], simde__m256d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_stream_pd(mem_addr, a); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256d), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_stream_pd + #define _mm256_stream_pd(mem_addr, a) simde_mm256_stream_pd(HEDLEY_REINTERPRET_CAST(double*, mem_addr), a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_stream_si256 (simde__m256i* mem_addr, simde__m256i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + _mm256_stream_si256(mem_addr, a); + #else + simde_memcpy(SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256i), &a, sizeof(a)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_stream_si256 + #define _mm256_stream_si256(mem_addr, a) simde_mm256_stream_si256(mem_addr, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_sub_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_sub_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_sub_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_sub_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f32 = a_.f32 - b_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[i] - b_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_sub_ps + #define _mm256_sub_ps(a, b) simde_mm256_sub_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_hsub_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_hsub_ps(a, b); + #else + return simde_mm256_sub_ps(simde_x_mm256_deinterleaveeven_ps(a, b), simde_x_mm256_deinterleaveodd_ps(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_hsub_ps + #define _mm256_hsub_ps(a, b) simde_mm256_hsub_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_sub_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_sub_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_sub_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_sub_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.f64 = a_.f64 - b_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[i] - b_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_sub_pd + #define _mm256_sub_pd(a, b) simde_mm256_sub_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_hsub_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_hsub_pd(a, b); + #else + return simde_mm256_sub_pd(simde_x_mm256_deinterleaveeven_pd(a, b), simde_x_mm256_deinterleaveodd_pd(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_hsub_pd + #define _mm256_hsub_pd(a, b) simde_mm256_hsub_pd(a, b) +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + HEDLEY_DIAGNOSTIC_PUSH + SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_ +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_undefined_ps (void) { + simde__m256_private r_; + +#if \ + defined(SIMDE_X86_AVX_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(5,0,0)) && \ + (!defined(__has_builtin) || HEDLEY_HAS_BUILTIN(__builtin_ia32_undef256)) + r_.n = _mm256_undefined_ps(); +#elif !defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + r_ = simde__m256_to_private(simde_mm256_setzero_ps()); +#endif + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_undefined_ps + #define _mm256_undefined_ps() simde_mm256_undefined_ps() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_undefined_pd (void) { + simde__m256d_private r_; + +#if \ + defined(SIMDE_X86_AVX_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(5,0,0)) && \ + (!defined(__has_builtin) || HEDLEY_HAS_BUILTIN(__builtin_ia32_undef256)) + r_.n = _mm256_undefined_pd(); +#elif !defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + r_ = simde__m256d_to_private(simde_mm256_setzero_pd()); +#endif + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_undefined_pd + #define _mm256_undefined_pd() simde_mm256_undefined_pd() +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_undefined_si256 (void) { + simde__m256i_private r_; +#if \ + defined(SIMDE_X86_AVX_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(5,0,0)) && \ + (!defined(__has_builtin) || HEDLEY_HAS_BUILTIN(__builtin_ia32_undef256)) + r_.n = _mm256_undefined_si256(); +#elif !defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + r_ = simde__m256i_to_private(simde_mm256_setzero_si256()); +#endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_undefined_si256 + #define _mm256_undefined_si256() simde_mm256_undefined_si256() +#endif + +#if defined(SIMDE_DIAGNOSTIC_DISABLE_UNINITIALIZED_) + HEDLEY_DIAGNOSTIC_POP +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_xor_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_xor_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128[0] = simde_mm_xor_ps(a_.m128[0], b_.m128[0]); + r_.m128[1] = simde_mm_xor_ps(a_.m128[1], b_.m128[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] ^ b_.u32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_xor_ps + #define _mm256_xor_ps(a, b) simde_mm256_xor_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_xor_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_xor_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128d[0] = simde_mm_xor_pd(a_.m128d[0], b_.m128d[0]); + r_.m128d[1] = simde_mm_xor_pd(a_.m128d[1], b_.m128d[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = a_.u64[i] ^ b_.u64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_xor_pd + #define _mm256_xor_pd(a, b) simde_mm256_xor_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_xorsign_ps(simde__m256 dest, simde__m256 src) { + return simde_mm256_xor_ps(simde_mm256_and_ps(simde_mm256_set1_ps(-0.0f), src), dest); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_xorsign_pd(simde__m256d dest, simde__m256d src) { + return simde_mm256_xor_pd(simde_mm256_and_pd(simde_mm256_set1_pd(-0.0), src), dest); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_x_mm256_negate_ps(simde__m256 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return simde_mm256_xor_ps(a,_mm256_set1_ps(SIMDE_FLOAT32_C(-0.0))); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + + #if defined(SIMDE_VECTOR_NEGATE) + r_.f32 = -a_.f32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = -a_.f32[i]; + } + #endif + + return simde__m256_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_x_mm256_negate_pd(simde__m256d a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return simde_mm256_xor_pd(a, _mm256_set1_pd(SIMDE_FLOAT64_C(-0.0))); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + #if defined(SIMDE_VECTOR_NEGATE) + r_.f64 = -a_.f64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = -a_.f64[i]; + } + #endif + + return simde__m256d_from_private(r_); + #endif +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_unpackhi_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_unpackhi_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.f32, b_.f32, 2, 10, 3, 11, 6, 14, 7, 15); + #else + r_.f32[0] = a_.f32[2]; + r_.f32[1] = b_.f32[2]; + r_.f32[2] = a_.f32[3]; + r_.f32[3] = b_.f32[3]; + r_.f32[4] = a_.f32[6]; + r_.f32[5] = b_.f32[6]; + r_.f32[6] = a_.f32[7]; + r_.f32[7] = b_.f32[7]; + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpackhi_ps + #define _mm256_unpackhi_ps(a, b) simde_mm256_unpackhi_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_unpackhi_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_unpackhi_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.f64, b_.f64, 1, 5, 3, 7); + #else + r_.f64[0] = a_.f64[1]; + r_.f64[1] = b_.f64[1]; + r_.f64[2] = a_.f64[3]; + r_.f64[3] = b_.f64[3]; + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpackhi_pd + #define _mm256_unpackhi_pd(a, b) simde_mm256_unpackhi_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_unpacklo_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_unpacklo_ps(a, b); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.f32, b_.f32, 0, 8, 1, 9, 4, 12, 5, 13); + #else + r_.f32[0] = a_.f32[0]; + r_.f32[1] = b_.f32[0]; + r_.f32[2] = a_.f32[1]; + r_.f32[3] = b_.f32[1]; + r_.f32[4] = a_.f32[4]; + r_.f32[5] = b_.f32[4]; + r_.f32[6] = a_.f32[5]; + r_.f32[7] = b_.f32[5]; + #endif + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpacklo_ps + #define _mm256_unpacklo_ps(a, b) simde_mm256_unpacklo_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_unpacklo_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_unpacklo_pd(a, b); + #else + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.f64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.f64, b_.f64, 0, 4, 2, 6); + #else + r_.f64[0] = a_.f64[0]; + r_.f64[1] = b_.f64[0]; + r_.f64[2] = a_.f64[2]; + r_.f64[3] = b_.f64[2]; + #endif + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpacklo_pd + #define _mm256_unpacklo_pd(a, b) simde_mm256_unpacklo_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_zextps128_ps256 (simde__m128 a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_insertf128_ps(_mm256_setzero_ps(), a, 0); + #else + simde__m256_private r_; + + r_.m128_private[0] = simde__m128_to_private(a); + r_.m128_private[1] = simde__m128_to_private(simde_mm_setzero_ps()); + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_zextps128_ps256 + #define _mm256_zextps128_ps256(a) simde_mm256_zextps128_ps256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_zextpd128_pd256 (simde__m128d a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_insertf128_pd(_mm256_setzero_pd(), a, 0); + #else + simde__m256d_private r_; + + r_.m128d_private[0] = simde__m128d_to_private(a); + r_.m128d_private[1] = simde__m128d_to_private(simde_mm_setzero_pd()); + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_zextpd128_pd256 + #define _mm256_zextpd128_pd256(a) simde_mm256_zextpd128_pd256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_zextsi128_si256 (simde__m128i a) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_insertf128_si256(_mm256_setzero_si256(), a, 0); + #else + simde__m256i_private r_; + + r_.m128i_private[0] = simde__m128i_to_private(a); + r_.m128i_private[1] = simde__m128i_to_private(simde_mm_setzero_si128()); + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_zextsi128_si256 + #define _mm256_zextsi128_si256(a) simde_mm256_zextsi128_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testc_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_testc_ps(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_u32x4_shr(wasm_v128_or(wasm_v128_not(b_.wasm_v128), a_.wasm_v128), 31); + m = wasm_v128_and(m, simde_mm_movehl_ps(m, m)); + m = wasm_v128_and(m, simde_mm_shuffle_epi32(m, SIMDE_MM_SHUFFLE(3, 2, 0, 1))); + return wasm_i32x4_extract_lane(m, 0); + #else + uint_fast32_t r = 0; + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u32) / sizeof(a_.u32[0])) ; i++) { + r |= ~a_.u32[i] & b_.u32[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 31) & 1)); + #endif + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_testc_ps + #define _mm_testc_ps(a, b) simde_mm_testc_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testc_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_testc_pd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_u64x2_shr(wasm_v128_or(wasm_v128_not(b_.wasm_v128), a_.wasm_v128), 63); + return HEDLEY_STATIC_CAST(int, wasm_i64x2_extract_lane(m, 0) & wasm_i64x2_extract_lane(m, 1)); + #else + uint_fast64_t r = 0; + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + r |= ~a_.u64[i] & b_.u64[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 63) & 1)); + #endif + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_testc_pd + #define _mm_testc_pd(a, b) simde_mm_testc_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testc_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testc_ps(a, b); + #else + uint_fast32_t r = 0; + simde__m256_private + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u32) / sizeof(a_.u32[0])) ; i++) { + r |= ~a_.u32[i] & b_.u32[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 31) & 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testc_ps + #define _mm256_testc_ps(a, b) simde_mm256_testc_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testc_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testc_pd(a, b); + #else + uint_fast64_t r = 0; + simde__m256d_private + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + r |= ~a_.u64[i] & b_.u64[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 63) & 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testc_pd + #define _mm256_testc_pd(a, b) simde_mm256_testc_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testc_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testc_si256(a, b); + #else + int_fast32_t r = 0; + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.i32f) / sizeof(a_.i32f[0])) ; i++) { + r |= ~a_.i32f[i] & b_.i32f[i]; + } + + return HEDLEY_STATIC_CAST(int, !r); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testc_si256 + #define _mm256_testc_si256(a, b) simde_mm256_testc_si256(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testz_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_testz_ps(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_u32x4_shr(wasm_v128_not(wasm_v128_and(a_.wasm_v128, b_.wasm_v128)), 31); + m = wasm_v128_and(m, simde_mm_movehl_ps(m, m)); + m = wasm_v128_and(m, simde_mm_shuffle_epi32(m, SIMDE_MM_SHUFFLE(3, 2, 0, 1))); + return wasm_i32x4_extract_lane(m, 0); + #else + uint_fast32_t r = 0; + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u32) / sizeof(a_.u32[0])) ; i++) { + r |= a_.u32[i] & b_.u32[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 31) & 1)); + #endif + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_testz_ps + #define _mm_testz_ps(a, b) simde_mm_testz_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testz_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_testz_pd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_u64x2_shr(wasm_v128_not(wasm_v128_and(a_.wasm_v128, b_.wasm_v128)), 63); + return HEDLEY_STATIC_CAST(int, wasm_i64x2_extract_lane(m, 0) & wasm_i64x2_extract_lane(m, 1)); + #else + uint_fast64_t r = 0; + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + r |= a_.u64[i] & b_.u64[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 63) & 1)); + #endif + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_testz_pd + #define _mm_testz_pd(a, b) simde_mm_testz_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testz_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testz_ps(a, b); + #else + uint_fast32_t r = 0; + simde__m256_private + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u32) / sizeof(a_.u32[0])) ; i++) { + r |= a_.u32[i] & b_.u32[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 31) & 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testz_ps + #define _mm256_testz_ps(a, b) simde_mm256_testz_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testz_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testz_pd(a, b); + #else + uint_fast64_t r = 0; + simde__m256d_private + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + r |= a_.u64[i] & b_.u64[i]; + } + + return HEDLEY_STATIC_CAST(int, ((~r >> 63) & 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testz_pd + #define _mm256_testz_pd(a, b) simde_mm256_testz_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testz_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testz_si256(a, b); + #else + int_fast32_t r = 0; + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r = simde_mm_testz_si128(a_.m128i[0], b_.m128i[0]) && simde_mm_testz_si128(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.i32f) / sizeof(a_.i32f[0])) ; i++) { + r |= a_.i32f[i] & b_.i32f[i]; + } + + r = !r; + #endif + + return HEDLEY_STATIC_CAST(int, r); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testz_si256 + #define _mm256_testz_si256(a, b) simde_mm256_testz_si256(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testnzc_ps (simde__m128 a, simde__m128 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_testnzc_ps(a, b); + #else + simde__m128_private + a_ = simde__m128_to_private(a), + b_ = simde__m128_to_private(b); + + #if defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_u32x4_shr(wasm_v128_and(a_.wasm_v128, b_.wasm_v128), 31); + v128_t m2 = wasm_u32x4_shr(wasm_v128_andnot(b_.wasm_v128, a_.wasm_v128), 31); + m = wasm_v128_or(m, simde_mm_movehl_ps(m, m)); + m2 = wasm_v128_or(m2, simde_mm_movehl_ps(m2, m2)); + m = wasm_v128_or(m, simde_mm_shuffle_epi32(m, SIMDE_MM_SHUFFLE(3, 2, 0, 1))); + m2 = wasm_v128_or(m2, simde_mm_shuffle_epi32(m2, SIMDE_MM_SHUFFLE(3, 2, 0, 1))); + return wasm_i32x4_extract_lane(m, 0) & wasm_i32x4_extract_lane(m2, 0); + #else + uint32_t rz = 0, rc = 0; + for (size_t i = 0 ; i < (sizeof(a_.u32) / sizeof(a_.u32[0])) ; i++) { + rc |= ~a_.u32[i] & b_.u32[i]; + rz |= a_.u32[i] & b_.u32[i]; + } + + return + (rc >> ((sizeof(rc) * CHAR_BIT) - 1)) & + (rz >> ((sizeof(rz) * CHAR_BIT) - 1)); + #endif + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_testnzc_ps + #define _mm_testnzc_ps(a, b) simde_mm_testnzc_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm_testnzc_pd (simde__m128d a, simde__m128d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm_testnzc_pd(a, b); + #else + simde__m128d_private + a_ = simde__m128d_to_private(a), + b_ = simde__m128d_to_private(b); + #if defined(SIMDE_WASM_SIMD128_NATIVE) + v128_t m = wasm_u64x2_shr(wasm_v128_and(a_.wasm_v128, b_.wasm_v128), 63); + v128_t m2 = wasm_u64x2_shr(wasm_v128_andnot(b_.wasm_v128, a_.wasm_v128), 63); + return HEDLEY_STATIC_CAST(int, (wasm_i64x2_extract_lane(m, 0) | wasm_i64x2_extract_lane(m, 1)) + & (wasm_i64x2_extract_lane(m2, 0) | wasm_i64x2_extract_lane(m2, 1))); + #else + uint64_t rc = 0, rz = 0; + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + rc |= ~a_.u64[i] & b_.u64[i]; + rz |= a_.u64[i] & b_.u64[i]; + } + + return + (rc >> ((sizeof(rc) * CHAR_BIT) - 1)) & + (rz >> ((sizeof(rz) * CHAR_BIT) - 1)); + #endif + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm_testnzc_pd + #define _mm_testnzc_pd(a, b) simde_mm_testnzc_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testnzc_ps (simde__m256 a, simde__m256 b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testnzc_ps(a, b); + #else + uint32_t rc = 0, rz = 0; + simde__m256_private + a_ = simde__m256_to_private(a), + b_ = simde__m256_to_private(b); + + for (size_t i = 0 ; i < (sizeof(a_.u32) / sizeof(a_.u32[0])) ; i++) { + rc |= ~a_.u32[i] & b_.u32[i]; + rz |= a_.u32[i] & b_.u32[i]; + } + + return + (rc >> ((sizeof(rc) * CHAR_BIT) - 1)) & + (rz >> ((sizeof(rz) * CHAR_BIT) - 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testnzc_ps + #define _mm256_testnzc_ps(a, b) simde_mm256_testnzc_ps(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testnzc_pd (simde__m256d a, simde__m256d b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testnzc_pd(a, b); + #else + uint64_t rc = 0, rz = 0; + simde__m256d_private + a_ = simde__m256d_to_private(a), + b_ = simde__m256d_to_private(b); + + for (size_t i = 0 ; i < (sizeof(a_.u64) / sizeof(a_.u64[0])) ; i++) { + rc |= ~a_.u64[i] & b_.u64[i]; + rz |= a_.u64[i] & b_.u64[i]; + } + + return + (rc >> ((sizeof(rc) * CHAR_BIT) - 1)) & + (rz >> ((sizeof(rz) * CHAR_BIT) - 1)); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testnzc_pd + #define _mm256_testnzc_pd(a, b) simde_mm256_testnzc_pd(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_testnzc_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX_NATIVE) + return _mm256_testnzc_si256(a, b); + #else + int32_t rc = 0, rz = 0; + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + for (size_t i = 0 ; i < (sizeof(a_.i32f) / sizeof(a_.i32f[0])) ; i++) { + rc |= ~a_.i32f[i] & b_.i32f[i]; + rz |= a_.i32f[i] & b_.i32f[i]; + } + + return !!(rc & rz); + #endif +} +#if defined(SIMDE_X86_AVX_ENABLE_NATIVE_ALIASES) + #undef _mm256_testnzc_si256 + #define _mm256_testnzc_si256(a, b) simde_mm256_testnzc_si256(a, b) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_AVX_H) */ +/* :: End ../simde/simde/x86/avx.h :: */ + +HEDLEY_DIAGNOSTIC_PUSH +SIMDE_DISABLE_UNWANTED_DIAGNOSTICS +SIMDE_BEGIN_DECLS_ + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_abs_epi8 (simde__m256i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_abs_epi8(a); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_abs_epi8(a_.m128i[0]); + r_.m128i[1] = simde_mm_abs_epi8(a_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] < INT32_C(0)) ? -a_.i8[i] : a_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_abs_epi8 + #define _mm256_abs_epi8(a) simde_mm256_abs_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_abs_epi16 (simde__m256i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_abs_epi16(a); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_abs_epi16(a_.m128i[0]); + r_.m128i[1] = simde_mm_abs_epi16(a_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] < INT32_C(0)) ? -a_.i16[i] : a_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_abs_epi16 + #define _mm256_abs_epi16(a) simde_mm256_abs_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_abs_epi32(simde__m256i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_abs_epi32(a); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_abs_epi32(a_.m128i[0]); + r_.m128i[1] = simde_mm_abs_epi32(a_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0; i < (sizeof(r_.i32) / sizeof(r_.i32[0])); i++) { + r_.i32[i] = (a_.i32[i] < INT32_C(0)) ? -a_.i32[i] : a_.i32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_abs_epi32 + #define _mm256_abs_epi32(a) simde_mm256_abs_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_add_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_add_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_add_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_add_epi8(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = a_.i8 + b_.i8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] + b_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_add_epi8 + #define _mm256_add_epi8(a, b) simde_mm256_add_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_add_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_add_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_add_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_add_epi16(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 + b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] + b_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_add_epi16 + #define _mm256_add_epi16(a, b) simde_mm256_add_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_hadd_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_hadd_epi16(a, b); + #else + return simde_mm256_add_epi16(simde_x_mm256_deinterleaveeven_epi16(a, b), simde_x_mm256_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_hadd_epi16 + #define _mm256_hadd_epi16(a, b) simde_mm256_hadd_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_add_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_add_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_add_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_add_epi32(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 + b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] + b_.i32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_add_epi32 + #define _mm256_add_epi32(a, b) simde_mm256_add_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_hadd_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_hadd_epi32(a, b); + #else + return simde_mm256_add_epi32(simde_x_mm256_deinterleaveeven_epi32(a, b), simde_x_mm256_deinterleaveodd_epi32(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_hadd_epi32 + #define _mm256_hadd_epi32(a, b) simde_mm256_hadd_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_add_epi64 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_add_epi64(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_add_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_add_epi64(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) && !defined(SIMDE_BUG_CLANG_BAD_VI64_OPS) + r_.i64 = a_.i64 + b_.i64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] + b_.i64[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_add_epi64 + #define _mm256_add_epi64(a, b) simde_mm256_add_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_alignr_epi8 (simde__m256i a, simde__m256i b, int count) + SIMDE_REQUIRE_CONSTANT_RANGE(count, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + if (HEDLEY_UNLIKELY(count > 31)) + return simde_mm256_setzero_si256(); + + for (size_t h = 0 ; h < (sizeof(r_.m128i) / sizeof(r_.m128i[0])) ; h++) { + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.m128i_private[h].i8) / sizeof(r_.m128i_private[h].i8[0])) ; i++) { + const int srcpos = count + HEDLEY_STATIC_CAST(int, i); + if (srcpos > 31) { + r_.m128i_private[h].i8[i] = 0; + } else if (srcpos > 15) { + r_.m128i_private[h].i8[i] = a_.m128i_private[h].i8[(srcpos) & 15]; + } else { + r_.m128i_private[h].i8[i] = b_.m128i_private[h].i8[srcpos]; + } + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_alignr_epi8(a, b, count) _mm256_alignr_epi8(a, b, count) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_alignr_epi8(a, b, count) \ + simde_mm256_set_m128i( \ + simde_mm_alignr_epi8(simde_mm256_extracti128_si256(a, 1), simde_mm256_extracti128_si256(b, 1), (count)), \ + simde_mm_alignr_epi8(simde_mm256_extracti128_si256(a, 0), simde_mm256_extracti128_si256(b, 0), (count))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_alignr_epi8 + #define _mm256_alignr_epi8(a, b, count) simde_mm256_alignr_epi8(a, b, (count)) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_and_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_and_si256(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_and_si128(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_and_si128(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f & b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] & b_.i64[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_and_si256 + #define _mm256_and_si256(a, b) simde_mm256_and_si256(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_andnot_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_andnot_si256(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_andnot_si128(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_andnot_si128(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = ~(a_.i32f[i]) & b_.i32f[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_andnot_si256 + #define _mm256_andnot_si256(a, b) simde_mm256_andnot_si256(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_adds_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_adds_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_adds_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_adds_epi8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = simde_math_adds_i8(a_.i8[i], b_.i8[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_adds_epi8 + #define _mm256_adds_epi8(a, b) simde_mm256_adds_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_adds_epi16(simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_adds_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_adds_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_adds_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = simde_math_adds_i16(a_.i16[i], b_.i16[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_adds_epi16 + #define _mm256_adds_epi16(a, b) simde_mm256_adds_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_hadds_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_hadds_epi16(a, b); + #else + return simde_mm256_adds_epi16(simde_x_mm256_deinterleaveeven_epi16(a, b), simde_x_mm256_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_hadds_epi16 + #define _mm256_hadds_epi16(a, b) simde_mm256_hadds_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_adds_epu8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_adds_epu8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_adds_epu8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_adds_epu8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = simde_math_adds_u8(a_.u8[i], b_.u8[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_adds_epu8 + #define _mm256_adds_epu8(a, b) simde_mm256_adds_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_adds_epu16(simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_adds_epu16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_adds_epu16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_adds_epu16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = simde_math_adds_u16(a_.u16[i], b_.u16[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_adds_epu16 + #define _mm256_adds_epu16(a, b) simde_mm256_adds_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_avg_epu8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_avg_epu8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] + b_.u8[i] + 1) >> 1; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_avg_epu8 + #define _mm256_avg_epu8(a, b) simde_mm256_avg_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_avg_epu16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_avg_epu16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = (a_.u16[i] + b_.u16[i] + 1) >> 1; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_avg_epu16 + #define _mm256_avg_epu16(a, b) simde_mm256_avg_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_blend_epi32(simde__m128i a, simde__m128i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 15) { + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = ((imm8 >> i) & 1) ? b_.i32[i] : a_.i32[i]; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm_blend_epi32(a, b, imm8) _mm_blend_epi32(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm_blend_epi32(a, b, imm8) \ + simde_mm_castps_si128(simde_mm_blend_ps(simde_mm_castsi128_ps(a), simde_mm_castsi128_ps(b), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_blend_epi32 + #define _mm_blend_epi32(a, b, imm8) simde_mm_blend_epi32(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_blend_epi16(simde__m256i a, simde__m256i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = ((imm8 >> i%8) & 1) ? b_.i16[i] : a_.i16[i]; + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) && defined(SIMDE_BUG_CLANG_REV_234560) +# define simde_mm256_blend_epi16(a, b, imm8) _mm256_castpd_si256(_mm256_blend_epi16(a, b, imm8)) +#elif defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_blend_epi16(a, b, imm8) _mm256_blend_epi16(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_blend_epi16(a, b, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_blend_epi16(simde_mm256_extracti128_si256(a, 1), simde_mm256_extracti128_si256(b, 1), (imm8)), \ + simde_mm_blend_epi16(simde_mm256_extracti128_si256(a, 0), simde_mm256_extracti128_si256(b, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_blend_epi16 + #define _mm256_blend_epi16(a, b, imm8) simde_mm256_blend_epi16(a, b, imm8) +#endif + + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_blend_epi32(simde__m256i a, simde__m256i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = ((imm8 >> i) & 1) ? b_.i32[i] : a_.i32[i]; + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_blend_epi32(a, b, imm8) _mm256_blend_epi32(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_blend_epi32(a, b, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_blend_epi32(simde_mm256_extracti128_si256(a, 1), simde_mm256_extracti128_si256(b, 1), (imm8) >> 4), \ + simde_mm_blend_epi32(simde_mm256_extracti128_si256(a, 0), simde_mm256_extracti128_si256(b, 0), (imm8) & 0x0F)) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_blend_epi32 + #define _mm256_blend_epi32(a, b, imm8) simde_mm256_blend_epi32(a, b, imm8) +#endif + + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_blendv_epi8(simde__m256i a, simde__m256i b, simde__m256i mask) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_blendv_epi8(a, b, mask); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + mask_ = simde__m256i_to_private(mask); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_blendv_epi8(a_.m128i[0], b_.m128i[0], mask_.m128i[0]); + r_.m128i[1] = simde_mm_blendv_epi8(a_.m128i[1], b_.m128i[1], mask_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + if (mask_.u8[i] & 0x80) { + r_.u8[i] = b_.u8[i]; + } else { + r_.u8[i] = a_.u8[i]; + } + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_blendv_epi8(a, b, imm8) _mm256_blendv_epi8(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_blendv_epi8 + #define _mm256_blendv_epi8(a, b, mask) simde_mm256_blendv_epi8(a, b, mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_broadcastb_epi8 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_broadcastb_epi8(a); + #else + simde__m128i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[0]; + } + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcastb_epi8 + #define _mm_broadcastb_epi8(a) simde_mm_broadcastb_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_broadcastb_epi8 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_broadcastb_epi8(a); + #else + simde__m256i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[0]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastb_epi8 + #define _mm256_broadcastb_epi8(a) simde_mm256_broadcastb_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_broadcastw_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_broadcastw_epi16(a); + #else + simde__m128i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[0]; + } + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcastw_epi16 + #define _mm_broadcastw_epi16(a) simde_mm_broadcastw_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_broadcastw_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_broadcastw_epi16(a); + #else + simde__m256i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[0]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastw_epi16 + #define _mm256_broadcastw_epi16(a) simde_mm256_broadcastw_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_broadcastd_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_broadcastd_epi32(a); + #else + simde__m128i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[0]; + } + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcastd_epi32 + #define _mm_broadcastd_epi32(a) simde_mm_broadcastd_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_broadcastd_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_broadcastd_epi32(a); + #else + simde__m256i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[0]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastd_epi32 + #define _mm256_broadcastd_epi32(a) simde_mm256_broadcastd_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_broadcastq_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_broadcastq_epi64(a); + #else + simde__m128i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[0]; + } + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcastq_epi64 + #define _mm_broadcastq_epi64(a) simde_mm_broadcastq_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_broadcastq_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_broadcastq_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_= simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[0]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastq_epi64 + #define _mm256_broadcastq_epi64(a) simde_mm256_broadcastq_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_broadcastss_ps (simde__m128 a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_broadcastss_ps(a); + #else + simde__m128_private r_; + simde__m128_private a_= simde__m128_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[0]; + } + + return simde__m128_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcastss_ps + #define _mm_broadcastss_ps(a) simde_mm_broadcastss_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_broadcastss_ps (simde__m128 a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_broadcastss_ps(a); + #else + simde__m256_private r_; + simde__m128_private a_= simde__m128_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[0]; + } + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastss_ps + #define _mm256_broadcastss_ps(a) simde_mm256_broadcastss_ps(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_broadcastsd_pd (simde__m128d a) { + return simde_mm_movedup_pd(a); +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_broadcastsd_pd + #define _mm_broadcastsd_pd(a) simde_mm_broadcastsd_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_broadcastsd_pd (simde__m128d a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_broadcastsd_pd(a); + #else + simde__m256d_private r_; + simde__m128d_private a_= simde__m128d_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + r_.f64[i] = a_.f64[0]; + } + + return simde__m256d_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastsd_pd + #define _mm256_broadcastsd_pd(a) simde_mm256_broadcastsd_pd(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_broadcastsi128_si256 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(4,8,0)) + return _mm256_broadcastsi128_si256(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i_private[0] = a_; + r_.m128i_private[1] = a_; + #else + r_.i64[0] = a_.i64[0]; + r_.i64[1] = a_.i64[1]; + r_.i64[2] = a_.i64[0]; + r_.i64[3] = a_.i64[1]; + #endif + + return simde__m256i_from_private(r_); + #endif +} +#define simde_mm_broadcastsi128_si256(a) simde_mm256_broadcastsi128_si256(a) +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_broadcastsi128_si256 + #define _mm256_broadcastsi128_si256(a) simde_mm256_broadcastsi128_si256(a) + #undef _mm_broadcastsi128_si256 + #define _mm_broadcastsi128_si256(a) simde_mm256_broadcastsi128_si256(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_bslli_epi128 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + const int ssize = HEDLEY_STATIC_CAST(int, (sizeof(r_.i8) / sizeof(r_.i8[0]))); + + SIMDE_VECTORIZE + for (int i = 0 ; i < ssize ; i++) { + const int e = i - imm8; + if(i >= (ssize/2)) { + if(e >= (ssize/2) && e < ssize) + r_.i8[i] = a_.i8[e]; + else + r_.i8[i] = 0; + } + else{ + if(e >= 0 && e < (ssize/2)) + r_.i8[i] = a_.i8[e]; + else + r_.i8[i] = 0; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(4,8,0)) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,7,0) + #define simde_mm256_bslli_epi128(a, imm8) _mm256_bslli_epi128(a, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_bslli_epi128 + #define _mm256_bslli_epi128(a, imm8) simde_mm256_bslli_epi128(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_bsrli_epi128 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + const int ssize = HEDLEY_STATIC_CAST(int, (sizeof(r_.i8) / sizeof(r_.i8[0]))); + + SIMDE_VECTORIZE + for (int i = 0 ; i < ssize ; i++) { + const int e = i + imm8; + if(i < (ssize/2)) { + if(e >= 0 && e < (ssize/2)) + r_.i8[i] = a_.i8[e]; + else + r_.i8[i] = 0; + } + else{ + if(e >= (ssize/2) && e < ssize) + r_.i8[i] = a_.i8[e]; + else + r_.i8[i] = 0; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) && \ + (!defined(HEDLEY_GCC_VERSION) || HEDLEY_GCC_VERSION_CHECK(4,8,0)) && \ + SIMDE_DETECT_CLANG_VERSION_CHECK(3,7,0) + #define simde_mm256_bsrli_epi128(a, imm8) _mm256_bsrli_epi128(a, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_bsrli_epi128 + #define _mm256_bsrli_epi128(a, imm8) simde_mm256_bsrli_epi128(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpeq_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpeq_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpeq_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpeq_epi8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] == b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpeq_epi8 + #define _mm256_cmpeq_epi8(a, b) simde_mm256_cmpeq_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpeq_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpeq_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpeq_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpeq_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] == b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpeq_epi16 + #define _mm256_cmpeq_epi16(a, b) simde_mm256_cmpeq_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpeq_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpeq_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpeq_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpeq_epi32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] == b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpeq_epi32 + #define _mm256_cmpeq_epi32(a, b) simde_mm256_cmpeq_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpeq_epi64 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpeq_epi64(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpeq_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpeq_epi64(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = (a_.i64[i] == b_.i64[i]) ? ~INT64_C(0) : INT64_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpeq_epi64 + #define _mm256_cmpeq_epi64(a, b) simde_mm256_cmpeq_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpgt_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpgt_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpgt_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpgt_epi8(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = HEDLEY_STATIC_CAST(__typeof__(r_.i8), a_.i8 > b_.i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (a_.i8[i] > b_.i8[i]) ? ~INT8_C(0) : INT8_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpgt_epi8 + #define _mm256_cmpgt_epi8(a, b) simde_mm256_cmpgt_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpgt_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpgt_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpgt_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpgt_epi16(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 > b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] > b_.i16[i]) ? ~INT16_C(0) : INT16_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpgt_epi16 + #define _mm256_cmpgt_epi16(a, b) simde_mm256_cmpgt_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpgt_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpgt_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpgt_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpgt_epi32(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = HEDLEY_STATIC_CAST(__typeof__(r_.i32), a_.i32 > b_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = (a_.i32[i] > b_.i32[i]) ? ~INT32_C(0) : INT32_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpgt_epi32 + #define _mm256_cmpgt_epi32(a, b) simde_mm256_cmpgt_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cmpgt_epi64 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cmpgt_epi64(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_cmpgt_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_cmpgt_epi64(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = HEDLEY_STATIC_CAST(__typeof__(r_.i64), a_.i64 > b_.i64); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = (a_.i64[i] > b_.i64[i]) ? ~INT64_C(0) : INT64_C(0); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cmpgt_epi64 + #define _mm256_cmpgt_epi64(a, b) simde_mm256_cmpgt_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepi8_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepi8_epi16(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i16, a_.i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi8_epi16 + #define _mm256_cvtepi8_epi16(a) simde_mm256_cvtepi8_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepi8_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepi8_epi32(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.m64_private[0].i8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi8_epi32 + #define _mm256_cvtepi8_epi32(a) simde_mm256_cvtepi8_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepi8_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepi8_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i8[i]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi8_epi64 + #define _mm256_cvtepi8_epi64(a) simde_mm256_cvtepi8_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepi16_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepi16_epi32(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi16_epi32 + #define _mm256_cvtepi16_epi32(a) simde_mm256_cvtepi16_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepi16_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepi16_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i64, a_.m64_private[0].i16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi16_epi64 + #define _mm256_cvtepi16_epi64(a) simde_mm256_cvtepi16_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepi32_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepi32_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i64, a_.i32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepi32_epi64 + #define _mm256_cvtepi32_epi64(a) simde_mm256_cvtepi32_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepu8_epi16 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepu8_epi16(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i16, a_.u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.u8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepu8_epi16 + #define _mm256_cvtepu8_epi16(a) simde_mm256_cvtepu8_epi16(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepu8_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepu8_epi32(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.m64_private[0].u8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.u8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepu8_epi32 + #define _mm256_cvtepu8_epi32(a) simde_mm256_cvtepu8_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepu8_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepu8_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.u8[i]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepu8_epi64 + #define _mm256_cvtepu8_epi64(a) simde_mm256_cvtepu8_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepu16_epi32 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepu16_epi32(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i32, a_.u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.u16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepu16_epi32 + #define _mm256_cvtepu16_epi32(a) simde_mm256_cvtepu16_epi32(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepu16_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepu16_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i64, a_.m64_private[0].u16); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.u16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepu16_epi64 + #define _mm256_cvtepu16_epi64(a) simde_mm256_cvtepu16_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_cvtepu32_epi64 (simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_cvtepu32_epi64(a); + #else + simde__m256i_private r_; + simde__m128i_private a_ = simde__m128i_to_private(a); + + #if defined(SIMDE_CONVERT_VECTOR_) + SIMDE_CONVERT_VECTOR_(r_.i64, a_.u32); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.u32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_cvtepu32_epi64 + #define _mm256_cvtepu32_epi64(a) simde_mm256_cvtepu32_epi64(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_extract_epi8 (simde__m256i a, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 31){ + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.i8[index]; +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_extract_epi8(a, index) _mm256_extract_epi8(a, index) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_extract_epi8 + #define _mm256_extract_epi8(a, index) simde_mm256_extract_epi8(a, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_mm256_extract_epi16 (simde__m256i a, const int index) + SIMDE_REQUIRE_RANGE(index, 0, 15) { + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.i16[index]; +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_extract_epi16(a, index) _mm256_extract_epi16(a, index) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_extract_epi16 + #define _mm256_extract_epi16(a, index) simde_mm256_extract_epi16(a, index) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_extracti128_si256 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256i_private a_ = simde__m256i_to_private(a); + return a_.m128i[imm8]; +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_extracti128_si256(a, imm8) _mm256_extracti128_si256(a, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_extracti128_si256 + #define _mm256_extracti128_si256(a, imm8) simde_mm256_extracti128_si256(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_i32gather_epi32(const int32_t* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i32[i] = dst; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_i32gather_epi32(base_addr, vindex, scale) _mm_i32gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i32_gather_epi32 + #define _mm_i32gather_epi32(base_addr, vindex, scale) simde_mm_i32gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mask_i32gather_epi32(simde__m128i src, const int32_t* base_addr, simde__m128i vindex, simde__m128i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + src_ = simde__m128i_to_private(src), + mask_ = simde__m128i_to_private(mask), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i32[i] = dst; + } + else { + r_.i32[i] = src_.i32[i]; + } + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_mask_i32gather_epi32(src, base_addr, vindex, mask, scale) _mm_mask_i32gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i32gather_epi32 + #define _mm_mask_i32gather_epi32(src, base_addr, vindex, mask, scale) simde_mm_mask_i32gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_i32gather_epi32(const int32_t* base_addr, simde__m256i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i32[i] = dst; + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_i32gather_epi32(base_addr, vindex, scale) _mm256_i32gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i32_gather_epi32 + #define _mm256_i32gather_epi32(base_addr, vindex, scale) simde_mm256_i32gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mask_i32gather_epi32(simde__m256i src, const int32_t* base_addr, simde__m256i vindex, simde__m256i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex), + src_ = simde__m256i_to_private(src), + mask_ = simde__m256i_to_private(mask), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i32[i] = dst; + } + else { + r_.i32[i] = src_.i32[i]; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_mask_i32gather_epi32(src, base_addr, vindex, mask, scale) _mm256_mask_i32gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i32gather_epi32 + #define _mm256_mask_i32gather_epi32(src, base_addr, vindex, mask, scale) simde_mm256_mask_i32gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_i64gather_epi32(const int32_t* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i32[i] = dst; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_i64gather_epi32(base_addr, vindex, scale) _mm_i64gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i64_gather_epi32 + #define _mm_i64gather_epi32(base_addr, vindex, scale) simde_mm_i64gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mask_i64gather_epi32(simde__m128i src, const int32_t* base_addr, simde__m128i vindex, simde__m128i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + src_ = simde__m128i_to_private(src), + mask_ = simde__m128i_to_private(mask), + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i32[i] = dst; + } + else { + r_.i32[i] = src_.i32[i]; + } + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_mask_i64gather_epi32(src, base_addr, vindex, mask, scale) _mm_mask_i64gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i64gather_epi32 + #define _mm_mask_i64gather_epi32(src, base_addr, vindex, mask, scale) simde_mm_mask_i64gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_i64gather_epi32(const int32_t* base_addr, simde__m256i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m128i_private + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i32[i] = dst; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_i64gather_epi32(base_addr, vindex, scale) _mm256_i64gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i64_gather_epi32 + #define _mm256_i64gather_epi32(base_addr, vindex, scale) simde_mm256_i64gather_epi32(SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm256_mask_i64gather_epi32(simde__m128i src, const int32_t* base_addr, simde__m256i vindex, simde__m128i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m128i_private + src_ = simde__m128i_to_private(src), + mask_ = simde__m128i_to_private(mask), + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int32_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i32[i] = dst; + } + else { + r_.i32[i] = src_.i32[i]; + } + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_mask_i64gather_epi32(src, base_addr, vindex, mask, scale) _mm256_mask_i64gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int const*, int32_t const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i64gather_epi32 + #define _mm256_mask_i64gather_epi32(src, base_addr, vindex, mask, scale) simde_mm256_mask_i64gather_epi32(src, SIMDE_CHECKED_REINTERPRET_CAST(int32_t const*, int const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_i32gather_epi64(const int64_t* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i64[i] = dst; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm_i32gather_epi64(base_addr, vindex, scale) _mm_i32gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) + #else + #define simde_mm_i32gather_epi64(base_addr, vindex, scale) _mm_i32gather_epi64(HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i32_gather_epi64 + #define _mm_i32gather_epi64(base_addr, vindex, scale) simde_mm_i32gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mask_i32gather_epi64(simde__m128i src, const int64_t* base_addr, simde__m128i vindex, simde__m128i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + src_ = simde__m128i_to_private(src), + mask_ = simde__m128i_to_private(mask), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i64[i] = dst; + } + else { + r_.i64[i] = src_.i64[i]; + } + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm_mask_i32gather_epi64(src, base_addr, vindex, mask, scale) _mm_mask_i32gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) + #else + #define simde_mm_mask_i32gather_epi64(src, base_addr, vindex, mask, scale) _mm_mask_i32gather_epi64(src, HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, mask, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i32gather_epi64 + #define _mm_mask_i32gather_epi64(src, base_addr, vindex, mask, scale) simde_mm_mask_i32gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_i32gather_epi64(const int64_t* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m256i_private + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i64[i] = dst; + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm256_i32gather_epi64(base_addr, vindex, scale) _mm256_i32gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) + #else + #define simde_mm256_i32gather_epi64(base_addr, vindex, scale) _mm256_i32gather_epi64(HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i32_gather_epi64 + #define _mm256_i32gather_epi64(base_addr, vindex, scale) simde_mm256_i32gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mask_i32gather_epi64(simde__m256i src, const int64_t* base_addr, simde__m128i vindex, simde__m256i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + src_ = simde__m256i_to_private(src), + mask_ = simde__m256i_to_private(mask), + r_; + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i64[i] = dst; + } + else { + r_.i64[i] = src_.i64[i]; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm256_mask_i32gather_epi64(src, base_addr, vindex, mask, scale) _mm256_mask_i32gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) + #else + #define simde_mm256_mask_i32gather_epi64(src, base_addr, vindex, mask, scale) _mm256_mask_i32gather_epi64(src, HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, mask, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i32gather_epi64 + #define _mm256_mask_i32gather_epi64(src, base_addr, vindex, mask, scale) simde_mm256_mask_i32gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_i64gather_epi64(const int64_t* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i64[i] = dst; + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm_i64gather_epi64(base_addr, vindex, scale) _mm_i64gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) + #else + #define simde_mm_i64gather_epi64(base_addr, vindex, scale) _mm_i64gather_epi64(HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i64_gather_epi64 + #define _mm_i64gather_epi64(base_addr, vindex, scale) simde_mm_i64gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_mask_i64gather_epi64(simde__m128i src, const int64_t* base_addr, simde__m128i vindex, simde__m128i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex), + src_ = simde__m128i_to_private(src), + mask_ = simde__m128i_to_private(mask), + r_ = simde__m128i_to_private(simde_mm_setzero_si128()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i64[i] = dst; + } + else { + r_.i64[i] = src_.i64[i]; + } + } + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm_mask_i64gather_epi64(src, base_addr, vindex, mask, scale) _mm_mask_i64gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) + #else + #define simde_mm_mask_i64gather_epi64(src, base_addr, vindex, mask, scale) _mm_mask_i64gather_epi64(src, HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, mask, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i64gather_epi64 + #define _mm_mask_i64gather_epi64(src, base_addr, vindex, mask, scale) simde_mm_mask_i64gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_i64gather_epi64(const int64_t* base_addr, simde__m256i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex), + r_ = simde__m256i_to_private(simde_mm256_setzero_si256()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.i64[i] = dst; + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm256_i64gather_epi64(base_addr, vindex, scale) _mm256_i64gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) + #else + #define simde_mm256_i64gather_epi64(base_addr, vindex, scale) _mm256_i64gather_epi64(HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i64_gather_epi64 + #define _mm256_i64gather_epi64(base_addr, vindex, scale) simde_mm256_i64gather_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mask_i64gather_epi64(simde__m256i src, const int64_t* base_addr, simde__m256i vindex, simde__m256i mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex), + src_ = simde__m256i_to_private(src), + mask_ = simde__m256i_to_private(mask), + r_ = simde__m256i_to_private(simde_mm256_setzero_si256()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + int64_t dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.i64[i] = dst; + } + else { + r_.i64[i] = src_.i64[i]; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #if SIMDE_DETECT_CLANG_VERSION_CHECK(3,8,0) + #define simde_mm256_mask_i64gather_epi64(src, base_addr, vindex, mask, scale) _mm256_mask_i64gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) + #else + #define simde_mm256_mask_i64gather_epi64(src, base_addr, vindex, mask, scale) _mm256_mask_i64gather_epi64(src, HEDLEY_REINTERPRET_CAST(long long const*, base_addr), vindex, mask, scale) + #endif +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i64gather_epi64 + #define _mm256_mask_i64gather_epi64(src, base_addr, vindex, mask, scale) simde_mm256_mask_i64gather_epi64(src, HEDLEY_REINTERPRET_CAST(int64_t const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_i32gather_ps(const simde_float32* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128_private + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f32[i] = dst; + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_i32gather_ps(base_addr, vindex, scale) _mm_i32gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i32_gather_ps + #define _mm_i32gather_ps(base_addr, vindex, scale) simde_mm_i32gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_mask_i32gather_ps(simde__m128 src, const simde_float32* base_addr, simde__m128i vindex, simde__m128 mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128_private + src_ = simde__m128_to_private(src), + mask_ = simde__m128_to_private(mask), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f32[i] = dst; + } + else { + r_.f32[i] = src_.f32[i]; + } + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_mask_i32gather_ps(src, base_addr, vindex, mask, scale) _mm_mask_i32gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i32gather_ps + #define _mm_mask_i32gather_ps(src, base_addr, vindex, mask, scale) simde_mm_mask_i32gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_i32gather_ps(const simde_float32* base_addr, simde__m256i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m256_private + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f32[i] = dst; + } + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_i32gather_ps(base_addr, vindex, scale) _mm256_i32gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i32_gather_ps + #define _mm256_i32gather_ps(base_addr, vindex, scale) simde_mm256_i32gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_mask_i32gather_ps(simde__m256 src, const simde_float32* base_addr, simde__m256i vindex, simde__m256 mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m256_private + src_ = simde__m256_to_private(src), + mask_ = simde__m256_to_private(mask), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f32[i] = dst; + } + else { + r_.f32[i] = src_.f32[i]; + } + } + + return simde__m256_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_mask_i32gather_ps(src, base_addr, vindex, mask, scale) _mm256_mask_i32gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i32gather_ps + #define _mm256_mask_i32gather_ps(src, base_addr, vindex, mask, scale) simde_mm256_mask_i32gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_i64gather_ps(const simde_float32* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128_private + r_ = simde__m128_to_private(simde_mm_setzero_ps()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f32[i] = dst; + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_i64gather_ps(base_addr, vindex, scale) _mm_i64gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i64_gather_ps + #define _mm_i64gather_ps(base_addr, vindex, scale) simde_mm_i64gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm_mask_i64gather_ps(simde__m128 src, const simde_float32* base_addr, simde__m128i vindex, simde__m128 mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128_private + src_ = simde__m128_to_private(src), + mask_ = simde__m128_to_private(mask), + r_ = simde__m128_to_private(simde_mm_setzero_ps()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f32[i] = dst; + } + else { + r_.f32[i] = src_.f32[i]; + } + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_mask_i64gather_ps(src, base_addr, vindex, mask, scale) _mm_mask_i64gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(float const*, float32_t const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i64gather_ps + #define _mm_mask_i64gather_ps(src, base_addr, vindex, mask, scale) simde_mm_mask_i64gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm256_i64gather_ps(const simde_float32* base_addr, simde__m256i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m128_private + r_ = simde__m128_to_private(simde_mm_setzero_ps()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f32[i] = dst; + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_i64gather_ps(base_addr, vindex, scale) _mm256_i64gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i64_gather_ps + #define _mm256_i64gather_ps(base_addr, vindex, scale) simde_mm256_i64gather_ps(SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128 +simde_mm256_mask_i64gather_ps(simde__m128 src, const simde_float32* base_addr, simde__m256i vindex, simde__m128 mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m128_private + src_ = simde__m128_to_private(src), + mask_ = simde__m128_to_private(mask), + r_ = simde__m128_to_private(simde_mm_setzero_ps()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i32[i] >> 31) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float32 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f32[i] = dst; + } + else { + r_.f32[i] = src_.f32[i]; + } + } + + return simde__m128_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_mask_i64gather_ps(src, base_addr, vindex, mask, scale) _mm256_mask_i64gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(float const*, simde_float32 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i64gather_ps + #define _mm256_mask_i64gather_ps(src, base_addr, vindex, mask, scale) simde_mm256_mask_i64gather_ps(src, SIMDE_CHECKED_REINTERPRET_CAST(simde_float32 const*, float const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_i32gather_pd(const simde_float64* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128d_private + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f64[i] = dst; + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_i32gather_pd(base_addr, vindex, scale) _mm_i32gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i32_gather_pd + #define _mm_i32gather_pd(base_addr, vindex, scale) simde_mm_i32gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_mask_i32gather_pd(simde__m128d src, const simde_float64* base_addr, simde__m128i vindex, simde__m128d mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128d_private + src_ = simde__m128d_to_private(src), + mask_ = simde__m128d_to_private(mask), + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f64) / sizeof(r_.f64[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f64[i] = dst; + } + else { + r_.f64[i] = src_.f64[i]; + } + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_mask_i32gather_pd(src, base_addr, vindex, mask, scale) _mm_mask_i32gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i32gather_pd + #define _mm_mask_i32gather_pd(src, base_addr, vindex, mask, scale) simde_mm_mask_i32gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_i32gather_pd(const simde_float64* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m256d_private + r_; + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f64[i] = dst; + } + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_i32gather_pd(base_addr, vindex, scale) _mm256_i32gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i32_gather_pd + #define _mm256_i32gather_pd(base_addr, vindex, scale) simde_mm256_i32gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_mask_i32gather_pd(simde__m256d src, const simde_float64* base_addr, simde__m128i vindex, simde__m256d mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256d_private + src_ = simde__m256d_to_private(src), + mask_ = simde__m256d_to_private(mask), + r_; + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i32) / sizeof(vindex_.i32[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i32[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f64[i] = dst; + } + else { + r_.f64[i] = src_.f64[i]; + } + } + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_mask_i32gather_pd(src, base_addr, vindex, mask, scale) _mm256_mask_i32gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i32gather_pd + #define _mm256_mask_i32gather_pd(src, base_addr, vindex, mask, scale) simde_mm256_mask_i32gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_i64gather_pd(const simde_float64* base_addr, simde__m128i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128d_private + r_ = simde__m128d_to_private(simde_mm_setzero_pd()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f64[i] = dst; + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_i64gather_pd(base_addr, vindex, scale) _mm_i64gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_i64_gather_pd + #define _mm_i64gather_pd(base_addr, vindex, scale) simde_mm_i64gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128d +simde_mm_mask_i64gather_pd(simde__m128d src, const simde_float64* base_addr, simde__m128i vindex, simde__m128d mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m128i_private + vindex_ = simde__m128i_to_private(vindex); + simde__m128d_private + src_ = simde__m128d_to_private(src), + mask_ = simde__m128d_to_private(mask), + r_ = simde__m128d_to_private(simde_mm_setzero_pd()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f64[i] = dst; + } + else { + r_.f64[i] = src_.f64[i]; + } + } + + return simde__m128d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_mask_i64gather_pd(src, base_addr, vindex, mask, scale) _mm_mask_i64gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_mask_i64gather_pd + #define _mm_mask_i64gather_pd(src, base_addr, vindex, mask, scale) simde_mm_mask_i64gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_i64gather_pd(const simde_float64* base_addr, simde__m256i vindex, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m256d_private + r_ = simde__m256d_to_private(simde_mm256_setzero_pd()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + const uint8_t* src = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src, sizeof(dst)); + r_.f64[i] = dst; + } + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_i64gather_pd(base_addr, vindex, scale) _mm256_i64gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_i64_gather_pd + #define _mm256_i64gather_pd(base_addr, vindex, scale) simde_mm256_i64gather_pd(HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_mask_i64gather_pd(simde__m256d src, const simde_float64* base_addr, simde__m256i vindex, simde__m256d mask, const int32_t scale) + SIMDE_REQUIRE_CONSTANT(scale) + HEDLEY_REQUIRE_MSG((scale && scale <= 8 && !(scale & (scale - 1))), "`scale' must be a power of two less than or equal to 8") { + simde__m256i_private + vindex_ = simde__m256i_to_private(vindex); + simde__m256d_private + src_ = simde__m256d_to_private(src), + mask_ = simde__m256d_to_private(mask), + r_ = simde__m256d_to_private(simde_mm256_setzero_pd()); + const uint8_t* addr = HEDLEY_REINTERPRET_CAST(const uint8_t*, base_addr); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(vindex_.i64) / sizeof(vindex_.i64[0])) ; i++) { + if ((mask_.i64[i] >> 63) & 1) { + const uint8_t* src1 = addr + (HEDLEY_STATIC_CAST(size_t , vindex_.i64[i]) * HEDLEY_STATIC_CAST(size_t , scale)); + simde_float64 dst; + simde_memcpy(&dst, src1, sizeof(dst)); + r_.f64[i] = dst; + } + else { + r_.f64[i] = src_.f64[i]; + } + } + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_mask_i64gather_pd(src, base_addr, vindex, mask, scale) _mm256_mask_i64gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mask_i64gather_pd + #define _mm256_mask_i64gather_pd(src, base_addr, vindex, mask, scale) simde_mm256_mask_i64gather_pd(src, HEDLEY_REINTERPRET_CAST(simde_float64 const*, base_addr), vindex, mask, scale) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_inserti128_si256(simde__m256i a, simde__m128i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 1) { + simde__m256i_private a_ = simde__m256i_to_private(a); + simde__m128i_private b_ = simde__m128i_to_private(b); + + a_.m128i_private[ imm8 & 1 ] = b_; + + return simde__m256i_from_private(a_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_inserti128_si256(a, b, imm8) _mm256_inserti128_si256(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_inserti128_si256 + #define _mm256_inserti128_si256(a, b, imm8) simde_mm256_inserti128_si256(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_madd_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_madd_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_madd_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_madd_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_) / sizeof(r_.i16[0])) ; i += 2) { + r_.i32[i / 2] = (a_.i16[i] * b_.i16[i]) + (a_.i16[i + 1] * b_.i16[i + 1]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_madd_epi16 + #define _mm256_madd_epi16(a, b) simde_mm256_madd_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_maddubs_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_maddubs_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_maddubs_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_maddubs_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + const int idx = HEDLEY_STATIC_CAST(int, i) << 1; + int32_t ts = + (HEDLEY_STATIC_CAST(int16_t, a_.u8[ idx ]) * HEDLEY_STATIC_CAST(int16_t, b_.i8[ idx ])) + + (HEDLEY_STATIC_CAST(int16_t, a_.u8[idx + 1]) * HEDLEY_STATIC_CAST(int16_t, b_.i8[idx + 1])); + r_.i16[i] = (ts > INT16_MIN) ? ((ts < INT16_MAX) ? HEDLEY_STATIC_CAST(int16_t, ts) : INT16_MAX) : INT16_MIN; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_maddubs_epi16 + #define _mm256_maddubs_epi16(a, b) simde_mm256_maddubs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_maskload_epi32 (const int32_t mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m128i mask) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_maskload_epi32(mem_addr, mask); + #else + simde__m128i_private + mem_ = simde__m128i_to_private(simde_x_mm_loadu_epi32(mem_addr)), + r_, + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i32 = vandq_s32(mem_.neon_i32, vshrq_n_s32(mask_.neon_i32, 31)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = mem_.i32[i] & (mask_.i32[i] >> 31); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_maskload_epi32 + #define _mm_maskload_epi32(mem_addr, mask) simde_mm_maskload_epi32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_maskload_epi32 (const int32_t mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m256i mask) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_maskload_epi32(mem_addr, mask); + #else + simde__m256i_private + mask_ = simde__m256i_to_private(mask), + r_ = simde__m256i_to_private(simde_x_mm256_loadu_epi32(mem_addr)); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] &= mask_.i32[i] >> 31; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskload_epi32 + #define _mm256_maskload_epi32(mem_addr, mask) simde_mm256_maskload_epi32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_maskload_epi64 (const int64_t mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m128i mask) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_maskload_epi64(HEDLEY_REINTERPRET_CAST(const long long *, mem_addr), mask); + #else + simde__m128i_private + mem_ = simde__m128i_to_private(simde_x_mm_loadu_epi64((mem_addr))), + r_, + mask_ = simde__m128i_to_private(mask); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_i64 = vandq_s64(mem_.neon_i64, vshrq_n_s64(mask_.neon_i64, 63)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = mem_.i64[i] & (mask_.i64[i] >> 63); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_maskload_epi64 + #define _mm_maskload_epi64(mem_addr, mask) simde_mm_maskload_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_maskload_epi64 (const int64_t mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m256i mask) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_maskload_epi64(HEDLEY_REINTERPRET_CAST(const long long *, mem_addr), mask); + #else + simde__m256i_private + mask_ = simde__m256i_to_private(mask), + r_ = simde__m256i_to_private(simde_x_mm256_loadu_epi64((mem_addr))); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] &= mask_.i64[i] >> 63; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskload_epi64 + #define _mm256_maskload_epi64(mem_addr, mask) simde_mm256_maskload_epi64(HEDLEY_REINTERPRET_CAST(int64_t const*, mem_addr), mask) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_maskstore_epi32 (int32_t mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m128i mask, simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + _mm_maskstore_epi32(mem_addr, mask, a); + #else + simde__m128i_private mask_ = simde__m128i_to_private(mask); + simde__m128i_private a_ = simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.i32) / sizeof(a_.i32[0])) ; i++) { + if (mask_.u32[i] & (UINT32_C(1) << 31)) + mem_addr[i] = a_.i32[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_maskstore_epi32 + #define _mm_maskstore_epi32(mem_addr, mask, a) simde_mm_maskstore_epi32(HEDLEY_REINTERPRET_CAST(int32_t *, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_maskstore_epi32 (int32_t mem_addr[HEDLEY_ARRAY_PARAM(8)], simde__m256i mask, simde__m256i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + _mm256_maskstore_epi32(mem_addr, mask, a); + #else + simde__m256i_private mask_ = simde__m256i_to_private(mask); + simde__m256i_private a_ = simde__m256i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.i32) / sizeof(a_.i32[0])) ; i++) { + if (mask_.u32[i] & (UINT32_C(1) << 31)) + mem_addr[i] = a_.i32[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskstore_epi32 + #define _mm256_maskstore_epi32(mem_addr, mask, a) simde_mm256_maskstore_epi32(HEDLEY_REINTERPRET_CAST(int32_t *, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm_maskstore_epi64 (int64_t mem_addr[HEDLEY_ARRAY_PARAM(2)], simde__m128i mask, simde__m128i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + _mm_maskstore_epi64(HEDLEY_REINTERPRET_CAST(long long *, mem_addr), mask, a); + #else + simde__m128i_private mask_ = simde__m128i_to_private(mask); + simde__m128i_private a_ = simde__m128i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.i64) / sizeof(a_.i64[0])) ; i++) { + if (mask_.u64[i] >> 63) + mem_addr[i] = a_.i64[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_maskstore_epi64 + #define _mm_maskstore_epi64(mem_addr, mask, a) simde_mm_maskstore_epi64(HEDLEY_REINTERPRET_CAST(int64_t *, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +void +simde_mm256_maskstore_epi64 (int64_t mem_addr[HEDLEY_ARRAY_PARAM(4)], simde__m256i mask, simde__m256i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + _mm256_maskstore_epi64(HEDLEY_REINTERPRET_CAST(long long *, mem_addr), mask, a); + #else + simde__m256i_private mask_ = simde__m256i_to_private(mask); + simde__m256i_private a_ = simde__m256i_to_private(a); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(a_.i64) / sizeof(a_.i64[0])) ; i++) { + if (mask_.u64[i] & (UINT64_C(1) << 63)) + mem_addr[i] = a_.i64[i]; + } + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_maskstore_epi64 + #define _mm256_maskstore_epi64(mem_addr, mask, a) simde_mm256_maskstore_epi64(HEDLEY_REINTERPRET_CAST(int64_t *, mem_addr), mask, a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_max_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) && !defined(__PGI) + return _mm256_max_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_max_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_max_epi8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] > b_.i8[i] ? a_.i8[i] : b_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_epi8 + #define _mm256_max_epi8(a, b) simde_mm256_max_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_max_epu8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_max_epu8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_max_epu8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_max_epu8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] > b_.u8[i]) ? a_.u8[i] : b_.u8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_epu8 + #define _mm256_max_epu8(a, b) simde_mm256_max_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_max_epu16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_max_epu16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_max_epu16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_max_epu16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = (a_.u16[i] > b_.u16[i]) ? a_.u16[i] : b_.u16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_epu16 + #define _mm256_max_epu16(a, b) simde_mm256_max_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_max_epu32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_max_epu32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_max_epu32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_max_epu32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = (a_.u32[i] > b_.u32[i]) ? a_.u32[i] : b_.u32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_epu32 + #define _mm256_max_epu32(a, b) simde_mm256_max_epu32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_max_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_max_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_max_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_max_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] > b_.i16[i]) ? a_.i16[i] : b_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_epi16 + #define _mm256_max_epi16(a, b) simde_mm256_max_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_max_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_max_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_max_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_max_epi32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] > b_.i32[i] ? a_.i32[i] : b_.i32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_max_epi32 + #define _mm256_max_epi32(a, b) simde_mm256_max_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_min_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) && !defined(__PGI) + return _mm256_min_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_min_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_min_epi8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] < b_.i8[i] ? a_.i8[i] : b_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_epi8 + #define _mm256_min_epi8(a, b) simde_mm256_min_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_min_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_min_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_min_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_min_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (a_.i16[i] < b_.i16[i]) ? a_.i16[i] : b_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_epi16 + #define _mm256_min_epi16(a, b) simde_mm256_min_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_min_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_min_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_min_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_min_epi32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] < b_.i32[i] ? a_.i32[i] : b_.i32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_epi32 + #define _mm256_min_epi32(a, b) simde_mm256_min_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_min_epu8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_min_epu8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_min_epu8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_min_epu8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = (a_.u8[i] < b_.u8[i]) ? a_.u8[i] : b_.u8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_epu8 + #define _mm256_min_epu8(a, b) simde_mm256_min_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_min_epu16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_min_epu16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_min_epu16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_min_epu16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = (a_.u16[i] < b_.u16[i]) ? a_.u16[i] : b_.u16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_epu16 + #define _mm256_min_epu16(a, b) simde_mm256_min_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_min_epu32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_min_epu32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_min_epu32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_min_epu32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = (a_.u32[i] < b_.u32[i]) ? a_.u32[i] : b_.u32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_min_epu32 + #define _mm256_min_epu32(a, b) simde_mm256_min_epu32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int32_t +simde_mm256_movemask_epi8 (simde__m256i a) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_movemask_epi8(a); + #else + simde__m256i_private a_ = simde__m256i_to_private(a); + uint32_t r = 0; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + for (size_t i = 0 ; i < (sizeof(a_.m128i) / sizeof(a_.m128i[0])) ; i++) { + r |= HEDLEY_STATIC_CAST(uint32_t,simde_mm_movemask_epi8(a_.m128i[i])) << (16 * i); + } + #else + r = 0; + SIMDE_VECTORIZE_REDUCTION(|:r) + for (size_t i = 0 ; i < (sizeof(a_.u8) / sizeof(a_.u8[0])) ; i++) { + r |= HEDLEY_STATIC_CAST(uint32_t, (a_.u8[31 - i] >> 7)) << (31 - i); + } + #endif + + return HEDLEY_STATIC_CAST(int32_t, r); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_movemask_epi8 + #define _mm256_movemask_epi8(a) simde_mm256_movemask_epi8(a) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mpsadbw_epu8 (simde__m256i a, simde__m256i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + const int a_offset1 = imm8 & 4; + const int b_offset1 = (imm8 & 3) << 2; + const int a_offset2 = (imm8 >> 3) & 4; + const int b_offset2 = ((imm8 >> 3) & 3) << 2; + + #if defined(simde_math_abs) + const int halfway_point = HEDLEY_STATIC_CAST(int, (sizeof(r_.u16) / sizeof(r_.u16[0])) ) / 2; + for (int i = 0 ; i < halfway_point ; i++) { + r_.u16[i] = + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset1 + i + 0] - b_.u8[b_offset1 + 0]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset1 + i + 1] - b_.u8[b_offset1 + 1]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset1 + i + 2] - b_.u8[b_offset1 + 2]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[a_offset1 + i + 3] - b_.u8[b_offset1 + 3]))); + r_.u16[halfway_point + i] = + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[2 * halfway_point + a_offset2 + i + 0] - b_.u8[2 * halfway_point + b_offset2 + 0]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[2 * halfway_point + a_offset2 + i + 1] - b_.u8[2 * halfway_point + b_offset2 + 1]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[2 * halfway_point + a_offset2 + i + 2] - b_.u8[2 * halfway_point + b_offset2 + 2]))) + + HEDLEY_STATIC_CAST(uint16_t, simde_math_abs(HEDLEY_STATIC_CAST(int, a_.u8[2 * halfway_point + a_offset2 + i + 3] - b_.u8[2 * halfway_point + b_offset2 + 3]))); + } + #else + HEDLEY_UNREACHABLE(); + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) && SIMDE_DETECT_CLANG_VERSION_CHECK(3,9,0) + #define simde_mm256_mpsadbw_epu8(a, b, imm8) _mm256_mpsadbw_epu8(a, b, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) + #define simde_mm256_mpsadbw_epu8(a, b, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_mpsadbw_epu8(simde_mm256_extracti128_si256(a, 1), simde_mm256_extracti128_si256(b, 1), (imm8 >> 3)), \ + simde_mm_mpsadbw_epu8(simde_mm256_extracti128_si256(a, 0), simde_mm256_extracti128_si256(b, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mpsadbw_epu8 + #define _mm256_mpsadbw_epu8(a, b, imm8) simde_mm256_mpsadbw_epu8(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mul_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mul_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_mul_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_mul_epi32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = + HEDLEY_STATIC_CAST(int64_t, a_.i32[i * 2]) * + HEDLEY_STATIC_CAST(int64_t, b_.i32[i * 2]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) +# define _mm256_mul_epi32(a, b) simde_mm256_mul_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mul_epu32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mul_epu32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_mul_epu32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_mul_epu32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = HEDLEY_STATIC_CAST(uint64_t, a_.u32[i * 2]) * HEDLEY_STATIC_CAST(uint64_t, b_.u32[i * 2]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) +# define _mm256_mul_epu32(a, b) simde_mm256_mul_epu32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mulhi_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mulhi_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, (HEDLEY_STATIC_CAST(uint32_t, HEDLEY_STATIC_CAST(int32_t, a_.i16[i]) * HEDLEY_STATIC_CAST(int32_t, b_.i16[i])) >> 16)); + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) +# define _mm256_mulhi_epi16(a, b) simde_mm256_mulhi_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mulhi_epu16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mulhi_epu16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = HEDLEY_STATIC_CAST(uint16_t, HEDLEY_STATIC_CAST(uint32_t, a_.u16[i]) * HEDLEY_STATIC_CAST(uint32_t, b_.u16[i]) >> 16); + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) +# define _mm256_mulhi_epu16(a, b) simde_mm256_mulhi_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mulhrs_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mulhrs_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, (((HEDLEY_STATIC_CAST(int32_t, a_.i16[i]) * HEDLEY_STATIC_CAST(int32_t, b_.i16[i])) + 0x4000) >> 15)); + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) +# define _mm256_mulhrs_epi16(a, b) simde_mm256_mulhrs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mullo_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mullo_epi16(a, b); + #else + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + r_; + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, a_.i16[i] * b_.i16[i]); + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mullo_epi16 + #define _mm256_mullo_epi16(a, b) simde_mm256_mullo_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_mullo_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_mullo_epi32(a, b); + #else + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + r_; + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = HEDLEY_STATIC_CAST(int32_t, a_.i32[i] * b_.i32[i]); + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_mullo_epi32 + #define _mm256_mullo_epi32(a, b) simde_mm256_mullo_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_mullo_epu32 (simde__m256i a, simde__m256i b) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.u32 = a_.u32 * b_.u32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] * b_.u32[i]; + } + #endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_or_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_or_si256(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_or_si128(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_or_si128(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f | b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32f) / sizeof(r_.i32f[0])) ; i++) { + r_.i32f[i] = a_.i32f[i] | b_.i32f[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_or_si256 + #define _mm256_or_si256(a, b) simde_mm256_or_si256(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_packs_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_packs_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_packs_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_packs_epi16(a_.m128i[1], b_.m128i[1]); + #else + const size_t halfway_point = (sizeof(r_.i8) / sizeof(r_.i8[0]))/2; + const size_t quarter_point = (sizeof(r_.i8) / sizeof(r_.i8[0]))/4; + SIMDE_VECTORIZE + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.i8[i] = (a_.i16[i] > INT8_MAX) ? INT8_MAX : ((a_.i16[i] < INT8_MIN) ? INT8_MIN : HEDLEY_STATIC_CAST(int8_t, a_.i16[i])); + r_.i8[i + quarter_point] = (b_.i16[i] > INT8_MAX) ? INT8_MAX : ((b_.i16[i] < INT8_MIN) ? INT8_MIN : HEDLEY_STATIC_CAST(int8_t, b_.i16[i])); + r_.i8[halfway_point + i] = (a_.i16[quarter_point + i] > INT8_MAX) ? INT8_MAX : ((a_.i16[quarter_point + i] < INT8_MIN) ? INT8_MIN : HEDLEY_STATIC_CAST(int8_t, a_.i16[quarter_point + i])); + r_.i8[halfway_point + i + quarter_point] = (b_.i16[quarter_point + i] > INT8_MAX) ? INT8_MAX : ((b_.i16[quarter_point + i] < INT8_MIN) ? INT8_MIN : HEDLEY_STATIC_CAST(int8_t, b_.i16[quarter_point + i])); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_packs_epi16 + #define _mm256_packs_epi16(a, b) simde_mm256_packs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_packs_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_packs_epi32(a, b); + #else + simde__m256i_private + r_, + v_[] = { + simde__m256i_to_private(a), + simde__m256i_to_private(b) + }; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_packs_epi32(v_[0].m128i[0], v_[1].m128i[0]); + r_.m128i[1] = simde_mm_packs_epi32(v_[0].m128i[1], v_[1].m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + const int32_t v = v_[(i >> 2) & 1].i32[(i & 11) - ((i & 8) >> 1)]; + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, (v > INT16_MAX) ? INT16_MAX : ((v < INT16_MIN) ? INT16_MIN : v)); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_packs_epi32 + #define _mm256_packs_epi32(a, b) simde_mm256_packs_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_packus_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_packus_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_packus_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_packus_epi16(a_.m128i[1], b_.m128i[1]); + #else + const size_t halfway_point = (sizeof(r_.i8) / sizeof(r_.i8[0])) / 2; + const size_t quarter_point = (sizeof(r_.i8) / sizeof(r_.i8[0])) / 4; + SIMDE_VECTORIZE + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.u8[i] = (a_.i16[i] > UINT8_MAX) ? UINT8_MAX : ((a_.i16[i] < 0) ? UINT8_C(0) : HEDLEY_STATIC_CAST(uint8_t, a_.i16[i])); + r_.u8[i + quarter_point] = (b_.i16[i] > UINT8_MAX) ? UINT8_MAX : ((b_.i16[i] < 0) ? UINT8_C(0) : HEDLEY_STATIC_CAST(uint8_t, b_.i16[i])); + r_.u8[halfway_point + i] = (a_.i16[quarter_point + i] > UINT8_MAX) ? UINT8_MAX : ((a_.i16[quarter_point + i] < 0) ? UINT8_C(0) : HEDLEY_STATIC_CAST(uint8_t, a_.i16[quarter_point + i])); + r_.u8[halfway_point + i + quarter_point] = (b_.i16[quarter_point + i] > UINT8_MAX) ? UINT8_MAX : ((b_.i16[quarter_point + i] < 0) ? UINT8_C(0) : HEDLEY_STATIC_CAST(uint8_t, b_.i16[quarter_point + i])); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_packus_epi16 + #define _mm256_packus_epi16(a, b) simde_mm256_packus_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_packus_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_packus_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_packus_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_packus_epi32(a_.m128i[1], b_.m128i[1]); + #else + const size_t halfway_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 2; + const size_t quarter_point = (sizeof(r_.i16) / sizeof(r_.i16[0])) / 4; + SIMDE_VECTORIZE + for (size_t i = 0 ; i < quarter_point ; i++) { + r_.u16[i] = (a_.i32[i] > UINT16_MAX) ? UINT16_MAX : ((a_.i32[i] < 0) ? UINT16_C(0) : HEDLEY_STATIC_CAST(uint16_t, a_.i32[i])); + r_.u16[i + quarter_point] = (b_.i32[i] > UINT16_MAX) ? UINT16_MAX : ((b_.i32[i] < 0) ? UINT16_C(0) : HEDLEY_STATIC_CAST(uint16_t, b_.i32[i])); + r_.u16[halfway_point + i] = (a_.i32[quarter_point + i] > UINT16_MAX) ? UINT16_MAX : ((a_.i32[quarter_point + i] < 0) ? UINT16_C(0) : HEDLEY_STATIC_CAST(uint16_t, a_.i32[quarter_point + i])); + r_.u16[halfway_point + i + quarter_point] = (b_.i32[quarter_point + i] > UINT16_MAX) ? UINT16_MAX : ((b_.i32[quarter_point + i] < 0) ? UINT16_C(0) : HEDLEY_STATIC_CAST(uint16_t, b_.i32[quarter_point + i])); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_packus_epi32 + #define _mm256_packus_epi32(a, b) simde_mm256_packus_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_permute2x128_si256 (simde__m256i a, simde__m256i b, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + r_.m128i_private[0] = (imm8 & 0x08) ? simde__m128i_to_private(simde_mm_setzero_si128()) : ((imm8 & 0x02) ? b_.m128i_private[(imm8 ) & 1] : a_.m128i_private[(imm8 ) & 1]); + r_.m128i_private[1] = (imm8 & 0x80) ? simde__m128i_to_private(simde_mm_setzero_si128()) : ((imm8 & 0x20) ? b_.m128i_private[(imm8 >> 4) & 1] : a_.m128i_private[(imm8 >> 4) & 1]); + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_permute2x128_si256(a, b, imm8) _mm256_permute2x128_si256(a, b, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute2x128_si256 + #define _mm256_permute2x128_si256(a, b, imm8) simde_mm256_permute2x128_si256(a, b, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_permute4x64_epi64 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + r_.i64[0] = (imm8 & 0x02) ? a_.i64[((imm8 ) & 1)+2] : a_.i64[(imm8 ) & 1]; + r_.i64[1] = (imm8 & 0x08) ? a_.i64[((imm8 >> 2 ) & 1)+2] : a_.i64[(imm8 >> 2 ) & 1]; + r_.i64[2] = (imm8 & 0x20) ? a_.i64[((imm8 >> 4 ) & 1)+2] : a_.i64[(imm8 >> 4 ) & 1]; + r_.i64[3] = (imm8 & 0x80) ? a_.i64[((imm8 >> 6 ) & 1)+2] : a_.i64[(imm8 >> 6 ) & 1]; + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_permute4x64_epi64(a, imm8) _mm256_permute4x64_epi64(a, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute4x64_epi64 + #define _mm256_permute4x64_epi64(a, imm8) simde_mm256_permute4x64_epi64(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256d +simde_mm256_permute4x64_pd (simde__m256d a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256d_private + r_, + a_ = simde__m256d_to_private(a); + + r_.f64[0] = (imm8 & 0x02) ? a_.f64[((imm8 ) & 1)+2] : a_.f64[(imm8 ) & 1]; + r_.f64[1] = (imm8 & 0x08) ? a_.f64[((imm8 >> 2 ) & 1)+2] : a_.f64[(imm8 >> 2 ) & 1]; + r_.f64[2] = (imm8 & 0x20) ? a_.f64[((imm8 >> 4 ) & 1)+2] : a_.f64[(imm8 >> 4 ) & 1]; + r_.f64[3] = (imm8 & 0x80) ? a_.f64[((imm8 >> 6 ) & 1)+2] : a_.f64[(imm8 >> 6 ) & 1]; + + return simde__m256d_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_permute4x64_pd(a, imm8) _mm256_permute4x64_pd(a, imm8) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_permute4x64_pd + #define _mm256_permute4x64_pd(a, imm8) simde_mm256_permute4x64_pd(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_permutevar8x32_epi32 (simde__m256i a, simde__m256i idx) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_permutevar8x32_epi32(a, idx); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + idx_ = simde__m256i_to_private(idx); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[idx_.i32[i] & 7]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_permutevar8x32_epi32 + #define _mm256_permutevar8x32_epi32(a, idx) simde_mm256_permutevar8x32_epi32(a, idx) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256 +simde_mm256_permutevar8x32_ps (simde__m256 a, simde__m256i idx) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_permutevar8x32_ps(a, idx); + #else + simde__m256_private + r_, + a_ = simde__m256_to_private(a); + simde__m256i_private + idx_ = simde__m256i_to_private(idx); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.f32) / sizeof(r_.f32[0])) ; i++) { + r_.f32[i] = a_.f32[idx_.i32[i] & 7]; + } + + return simde__m256_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_permutevar8x32_ps + #define _mm256_permutevar8x32_ps(a, idx) simde_mm256_permutevar8x32_ps(a, idx) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sad_epu8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sad_epu8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sad_epu8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sad_epu8(a_.m128i[1], b_.m128i[1]); + #else + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + uint16_t tmp = 0; + SIMDE_VECTORIZE_REDUCTION(+:tmp) + for (size_t j = 0 ; j < ((sizeof(r_.u8) / sizeof(r_.u8[0])) / 4) ; j++) { + const size_t e = j + (i * 8); + tmp += (a_.u8[e] > b_.u8[e]) ? (a_.u8[e] - b_.u8[e]) : (b_.u8[e] - a_.u8[e]); + } + r_.i64[i] = tmp; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sad_epu8 + #define _mm256_sad_epu8(a, b) simde_mm256_sad_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_shuffle_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_shuffle_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_shuffle_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_shuffle_epi8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < ((sizeof(r_.u8) / sizeof(r_.u8[0])) / 2) ; i++) { + r_.u8[ i ] = (b_.u8[ i ] & 0x80) ? 0 : a_.u8[(b_.u8[ i ] & 0x0f) ]; + r_.u8[i + 16] = (b_.u8[i + 16] & 0x80) ? 0 : a_.u8[(b_.u8[i + 16] & 0x0f) + 16]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_shuffle_epi8 + #define _mm256_shuffle_epi8(a, b) simde_mm256_shuffle_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_shuffle_epi32 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + for (size_t i = 0 ; i < ((sizeof(r_.i32) / sizeof(r_.i32[0])) / 2) ; i++) { + r_.i32[i] = a_.i32[(imm8 >> (i * 2)) & 3]; + } + for (size_t i = 0 ; i < ((sizeof(r_.i32) / sizeof(r_.i32[0])) / 2) ; i++) { + r_.i32[i + 4] = a_.i32[((imm8 >> (i * 2)) & 3) + 4]; + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_shuffle_epi32(a, imm8) _mm256_shuffle_epi32(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) && !defined(__PGI) +# define simde_mm256_shuffle_epi32(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_shuffle_epi32(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_shuffle_epi32(simde_mm256_extracti128_si256(a, 0), (imm8))) +#elif defined(SIMDE_SHUFFLE_VECTOR_) +# define simde_mm256_shuffle_epi32(a, imm8) (__extension__ ({ \ + const simde__m256i_private simde__tmp_a_ = simde__m256i_to_private(a); \ + simde__m256i_from_private((simde__m256i_private) { .i32 = \ + SIMDE_SHUFFLE_VECTOR_(32, 32, \ + (simde__tmp_a_).i32, \ + (simde__tmp_a_).i32, \ + ((imm8) ) & 3, \ + ((imm8) >> 2) & 3, \ + ((imm8) >> 4) & 3, \ + ((imm8) >> 6) & 3, \ + (((imm8) ) & 3) + 4, \ + (((imm8) >> 2) & 3) + 4, \ + (((imm8) >> 4) & 3) + 4, \ + (((imm8) >> 6) & 3) + 4) }); })) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_shuffle_epi32 + #define _mm256_shuffle_epi32(a, imm8) simde_mm256_shuffle_epi32(a, imm8) +#endif + +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_shufflehi_epi16(a, imm8) _mm256_shufflehi_epi16(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_shufflehi_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_shufflehi_epi16(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_shufflehi_epi16(simde_mm256_extracti128_si256(a, 0), (imm8))) +#elif defined(SIMDE_SHUFFLE_VECTOR_) +# define simde_mm256_shufflehi_epi16(a, imm8) (__extension__ ({ \ + const simde__m256i_private simde__tmp_a_ = simde__m256i_to_private(a); \ + simde__m256i_from_private((simde__m256i_private) { .i16 = \ + SIMDE_SHUFFLE_VECTOR_(16, 32, \ + (simde__tmp_a_).i16, \ + (simde__tmp_a_).i16, \ + 0, 1, 2, 3, \ + (((imm8) ) & 3) + 4, \ + (((imm8) >> 2) & 3) + 4, \ + (((imm8) >> 4) & 3) + 4, \ + (((imm8) >> 6) & 3) + 4, \ + 8, 9, 10, 11, \ + ((((imm8) ) & 3) + 8 + 4), \ + ((((imm8) >> 2) & 3) + 8 + 4), \ + ((((imm8) >> 4) & 3) + 8 + 4), \ + ((((imm8) >> 6) & 3) + 8 + 4) \ + ) }); })) +#else +# define simde_mm256_shufflehi_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_shufflehi_epi16(simde_mm256_extracti128_si256(a, 1), imm8), \ + simde_mm_shufflehi_epi16(simde_mm256_extracti128_si256(a, 0), imm8)) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_shufflehi_epi16 + #define _mm256_shufflehi_epi16(a, imm8) simde_mm256_shufflehi_epi16(a, imm8) +#endif + +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_shufflelo_epi16(a, imm8) _mm256_shufflelo_epi16(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_shufflelo_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_shufflelo_epi16(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_shufflelo_epi16(simde_mm256_extracti128_si256(a, 0), (imm8))) +#elif defined(SIMDE_SHUFFLE_VECTOR_) +# define simde_mm256_shufflelo_epi16(a, imm8) (__extension__ ({ \ + const simde__m256i_private simde__tmp_a_ = simde__m256i_to_private(a); \ + simde__m256i_from_private((simde__m256i_private) { .i16 = \ + SIMDE_SHUFFLE_VECTOR_(16, 32, \ + (simde__tmp_a_).i16, \ + (simde__tmp_a_).i16, \ + (((imm8) ) & 3), \ + (((imm8) >> 2) & 3), \ + (((imm8) >> 4) & 3), \ + (((imm8) >> 6) & 3), \ + 4, 5, 6, 7, \ + ((((imm8) ) & 3) + 8), \ + ((((imm8) >> 2) & 3) + 8), \ + ((((imm8) >> 4) & 3) + 8), \ + ((((imm8) >> 6) & 3) + 8), \ + 12, 13, 14, 15) }); })) +#else +# define simde_mm256_shufflelo_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_shufflelo_epi16(simde_mm256_extracti128_si256(a, 1), imm8), \ + simde_mm_shufflelo_epi16(simde_mm256_extracti128_si256(a, 0), imm8)) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_shufflelo_epi16 + #define _mm256_shufflelo_epi16(a, imm8) simde_mm256_shufflelo_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sign_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sign_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = (b_.i8[i] < INT32_C(0)) ? -a_.i8[i] : a_.i8[i]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sign_epi8 + #define _mm256_sign_epi8(a, b) simde_mm256_sign_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sign_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sign_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = (b_.i16[i] < INT32_C(0)) ? -a_.i16[i] : a_.i16[i]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sign_epi16 + #define _mm256_sign_epi16(a, b) simde_mm256_sign_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sign_epi32(simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sign_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + SIMDE_VECTORIZE + for (size_t i = 0; i < (sizeof(r_.i32) / sizeof(r_.i32[0])); i++) { + r_.i32[i] = (b_.i32[i] < INT32_C(0)) ? -a_.i32[i] : a_.i32[i]; + } + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sign_epi32 + #define _mm256_sign_epi32(a, b) simde_mm256_sign_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sll_epi16 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sll_epi16(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sll_epi16(a_.m128i[0], count); + r_.m128i[1] = simde_mm_sll_epi16(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t, count_.i64[0]); + if (shift > 15) + return simde_mm256_setzero_si256(); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 << HEDLEY_STATIC_CAST(int16_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, a_.i16[i] << (shift)); + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sll_epi16 + #define _mm256_sll_epi16(a, count) simde_mm256_sll_epi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sll_epi32 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sll_epi32(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sll_epi32(a_.m128i[0], count); + r_.m128i[1] = simde_mm_sll_epi32(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t, count_.i64[0]); + if (shift > 31) + return simde_mm256_setzero_si256(); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 << HEDLEY_STATIC_CAST(int32_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = HEDLEY_STATIC_CAST(int32_t, a_.i32[i] << (shift)); + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sll_epi32 + #define _mm256_sll_epi32(a, count) simde_mm256_sll_epi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sll_epi64 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sll_epi64(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sll_epi64(a_.m128i[0], count); + r_.m128i[1] = simde_mm_sll_epi64(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t, count_.i64[0]); + if (shift > 63) + return simde_mm256_setzero_si256(); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i64 = a_.i64 << HEDLEY_STATIC_CAST(int64_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = HEDLEY_STATIC_CAST(int64_t, a_.i64[i] << (shift)); + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sll_epi64 + #define _mm256_sll_epi64(a, count) simde_mm256_sll_epi64(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_slli_epi16 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + /* Note: There is no consistency in how compilers handle values outside of + the expected range, hence the discrepancy between what we allow and what + Intel specifies. Some compilers will return 0, others seem to just mask + off everything outside of the range. */ + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) sv = vec_splats(HEDLEY_STATIC_CAST(unsigned short, imm8)); + for (size_t i = 0 ; i < (sizeof(a_.altivec_i16) / sizeof(a_.altivec_i16[0])) ; i++) { + r_.altivec_i16[i] = vec_sl(a_.altivec_i16[i], sv); + } + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 << HEDLEY_STATIC_CAST(int16_t, imm8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = HEDLEY_STATIC_CAST(int16_t, a_.i16[i] << (imm8 & 0xff)); + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_slli_epi16(a, imm8) _mm256_slli_epi16(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_slli_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_slli_epi16(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_slli_epi16(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_slli_epi16 + #define _mm256_slli_epi16(a, imm8) simde_mm256_slli_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_slli_epi32 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) sv = vec_splats(HEDLEY_STATIC_CAST(unsigned int, imm8)); + for (size_t i = 0 ; i < (sizeof(a_.altivec_i32) / sizeof(a_.altivec_i32[0])) ; i++) { + r_.altivec_i32[i] = vec_sl(a_.altivec_i32[i], sv); + } + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 << HEDLEY_STATIC_CAST(int32_t, imm8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] << (imm8 & 0xff); + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_slli_epi32(a, imm8) _mm256_slli_epi32(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_slli_epi32(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_slli_epi32(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_slli_epi32(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_slli_epi32 + #define _mm256_slli_epi32(a, imm8) simde_mm256_slli_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_slli_epi64 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + +#if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i64 = a_.i64 << HEDLEY_STATIC_CAST(int64_t, imm8); +#else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] << (imm8 & 0xff); + } +#endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_slli_epi64(a, imm8) _mm256_slli_epi64(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_slli_epi64(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_slli_epi64(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_slli_epi64(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_slli_epi64 + #define _mm256_slli_epi64(a, imm8) simde_mm256_slli_epi64(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_slli_si256 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + for (size_t h = 0 ; h < (sizeof(r_.m128i_private) / sizeof(r_.m128i_private[0])) ; h++) { + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.m128i_private[h].i8) / sizeof(r_.m128i_private[h].i8[0])) ; i++) { + const int e = HEDLEY_STATIC_CAST(int, i) - imm8; + r_.m128i_private[h].i8[i] = (e >= 0) ? a_.m128i_private[h].i8[e] : 0; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_slli_si256(a, imm8) _mm256_slli_si256(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) && !defined(__PGI) +# define simde_mm256_slli_si256(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_slli_si128(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_slli_si128(simde_mm256_extracti128_si256(a, 0), (imm8))) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm256_slli_si256(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_bslli_si128(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_bslli_si128(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_slli_si256 + #define _mm256_slli_si256(a, imm8) simde_mm256_slli_si256(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sllv_epi32 (simde__m128i a, simde__m128i b) { + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + r_; + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + r_.neon_u32 = vshlq_u32(a_.neon_u32, vreinterpretq_s32_u32(b_.neon_u32)); + r_.neon_u32 = vandq_u32(r_.neon_u32, vcltq_u32(b_.neon_u32, vdupq_n_u32(32))); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = HEDLEY_STATIC_CAST(__typeof__(r_.u32), (b_.u32 < 32) & (a_.u32 << b_.u32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = (b_.u32[i] < 32) ? (a_.u32[i] << b_.u32[i]) : 0; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_sllv_epi32(a, b) _mm_sllv_epi32(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_sllv_epi32 + #define _mm_sllv_epi32(a, b) simde_mm_sllv_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sllv_epi32 (simde__m256i a, simde__m256i b) { + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sllv_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sllv_epi32(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = HEDLEY_STATIC_CAST(__typeof__(r_.u32), (b_.u32 < 32) & (a_.u32 << b_.u32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = (b_.u32[i] < 32) ? (a_.u32[i] << b_.u32[i]) : 0; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_sllv_epi32(a, b) _mm256_sllv_epi32(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sllv_epi32 + #define _mm256_sllv_epi32(a, b) simde_mm256_sllv_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_sllv_epi64 (simde__m128i a, simde__m128i b) { + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + r_; + + #if defined(SIMDE_ARM_NEON_A64V8_NATIVE) + r_.neon_u64 = vshlq_u64(a_.neon_u64, vreinterpretq_s64_u64(b_.neon_u64)); + r_.neon_u64 = vandq_u64(r_.neon_u64, vcltq_u64(b_.neon_u64, vdupq_n_u64(64))); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = HEDLEY_STATIC_CAST(__typeof__(r_.u64), (b_.u64 < 64) & (a_.u64 << b_.u64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = (b_.u64[i] < 64) ? (a_.u64[i] << b_.u64[i]) : 0; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_sllv_epi64(a, b) _mm_sllv_epi64(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_sllv_epi64 + #define _mm_sllv_epi64(a, b) simde_mm_sllv_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sllv_epi64 (simde__m256i a, simde__m256i b) { + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + r_; + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sllv_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sllv_epi64(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = HEDLEY_STATIC_CAST(__typeof__(r_.u64), (b_.u64 < 64) & (a_.u64 << b_.u64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = (b_.u64[i] < 64) ? (a_.u64[i] << b_.u64[i]) : 0; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_sllv_epi64(a, b) _mm256_sllv_epi64(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sllv_epi64 + #define _mm256_sllv_epi64(a, b) simde_mm256_sllv_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sra_epi16 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sra_epi16(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sra_epi16(a_.m128i[0], count); + r_.m128i[1] = simde_mm_sra_epi16(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t, count_.i64[0]); + + if (shift > 15) shift = 15; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 >> HEDLEY_STATIC_CAST(int16_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] >> shift; + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sra_epi16 + #define _mm256_sra_epi16(a, count) simde_mm256_sra_epi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sra_epi32 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sra_epi32(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sra_epi32(a_.m128i[0], count); + r_.m128i[1] = simde_mm_sra_epi32(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t, count_.i64[0]); + + if (shift > 31) shift = 31; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 >> HEDLEY_STATIC_CAST(int16_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] >> shift; + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sra_epi32 + #define _mm256_sra_epi32(a, count) simde_mm256_sra_epi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srai_epi16 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + unsigned int shift = HEDLEY_STATIC_CAST(unsigned int, imm8); + + if (shift > 15) shift = 15; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i16 = a_.i16 >> HEDLEY_STATIC_CAST(int16_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] >> shift; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_srai_epi16(a, imm8) _mm256_srai_epi16(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_srai_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_srai_epi16(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_srai_epi16(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srai_epi16 + #define _mm256_srai_epi16(a, imm8) simde_mm256_srai_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srai_epi32 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + unsigned int shift = HEDLEY_STATIC_CAST(unsigned int, imm8); + + if (shift > 31) shift = 31; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.i32 = a_.i32 >> HEDLEY_STATIC_CAST(int16_t, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] >> shift; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_srai_epi32(a, imm8) _mm256_srai_epi32(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_srai_epi32(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_srai_epi32(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_srai_epi32(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srai_epi32 + #define _mm256_srai_epi32(a, imm8) simde_mm256_srai_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srav_epi32 (simde__m128i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm_srav_epi32(a, count); + #else + simde__m128i_private + r_, + a_ = simde__m128i_to_private(a), + count_ = simde__m128i_to_private(count); + + #if defined(SIMDE_ARM_NEON_A32V7_NATIVE) + int32x4_t cnt = vreinterpretq_s32_u32(vminq_u32(count_.neon_u32, vdupq_n_u32(31))); + r_.neon_i32 = vshlq_s32(a_.neon_i32, vnegq_s32(cnt)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + uint32_t shift = HEDLEY_STATIC_CAST(uint32_t, count_.i32[i]); + r_.i32[i] = a_.i32[i] >> HEDLEY_STATIC_CAST(int, shift > 31 ? 31 : shift); + } + #endif + + return simde__m128i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_srav_epi32 + #define _mm_srav_epi32(a, count) simde_mm_srav_epi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srav_epi32 (simde__m256i a, simde__m256i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_srav_epi32(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + count_ = simde__m256i_to_private(count); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_srav_epi32(a_.m128i[0], count_.m128i[0]); + r_.m128i[1] = simde_mm_srav_epi32(a_.m128i[1], count_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + uint32_t shift = HEDLEY_STATIC_CAST(uint32_t, count_.i32[i]); + if (shift > 31) shift = 31; + r_.i32[i] = a_.i32[i] >> shift; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srav_epi32 + #define _mm256_srav_epi32(a, count) simde_mm256_srav_epi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srl_epi16 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_srl_epi16(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_srl_epi16(a_.m128i[0], count); + r_.m128i[1] = simde_mm_srl_epi16(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t , (count_.i64[0] > 16 ? 16 : count_.i64[0])); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u16 = a_.u16 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(16, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.u16[i] = a_.u16[i] >> (shift); + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srl_epi16 + #define _mm256_srl_epi16(a, count) simde_mm256_srl_epi16(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srl_epi32 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_srl_epi32(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_srl_epi32(a_.m128i[0], count); + r_.m128i[1] = simde_mm_srl_epi32(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t , (count_.i64[0] > 32 ? 32 : count_.i64[0])); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = a_.u32 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(32, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.u32[i] = a_.u32[i] >> (shift); + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srl_epi32 + #define _mm256_srl_epi32(a, count) simde_mm256_srl_epi32(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srl_epi64 (simde__m256i a, simde__m128i count) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_srl_epi64(a, count); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_srl_epi64(a_.m128i[0], count); + r_.m128i[1] = simde_mm_srl_epi64(a_.m128i[1], count); + #else + simde__m128i_private + count_ = simde__m128i_to_private(count); + + uint64_t shift = HEDLEY_STATIC_CAST(uint64_t , (count_.i64[0] > 64 ? 64 : count_.i64[0])); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = a_.u64 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(64, shift); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.u64[i] = a_.u64[i] >> (shift); + } + #endif + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srl_epi64 + #define _mm256_srl_epi64(a, count) simde_mm256_srl_epi64(a, count) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srli_epi16 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + if (imm8 > 15) + return simde_mm256_setzero_si256(); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_POWER_ALTIVEC_VECTOR(unsigned short) sv = vec_splats(HEDLEY_STATIC_CAST(unsigned short, imm8)); + for (size_t i = 0 ; i < (sizeof(a_.altivec_u16) / sizeof(a_.altivec_u16[0])) ; i++) { + r_.altivec_u16[i] = vec_sr(a_.altivec_u16[i], sv); + } + #else + if (HEDLEY_STATIC_CAST(unsigned int, imm8) > 15) { + simde_memset(&r_, 0, sizeof(r_)); + } else { + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u16 = a_.u16 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(16, imm8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = a_.u16[i] >> imm8; + } + #endif + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_srli_epi16(a, imm8) _mm256_srli_epi16(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_srli_epi16(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_srli_epi16(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_srli_epi16(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srli_epi16 + #define _mm256_srli_epi16(a, imm8) simde_mm256_srli_epi16(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srli_epi32 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + #if defined(SIMDE_POWER_ALTIVEC_P6_NATIVE) + SIMDE_POWER_ALTIVEC_VECTOR(unsigned int) sv = vec_splats(HEDLEY_STATIC_CAST(unsigned int, imm8)); + for (size_t i = 0 ; i < (sizeof(a_.altivec_u32) / sizeof(a_.altivec_u32[0])) ; i++) { + r_.altivec_u32[i] = vec_sr(a_.altivec_u32[i], sv); + } + #elif defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = a_.u32 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(16, imm8); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] >> imm8; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_srli_epi32(a, imm8) _mm256_srli_epi32(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_srli_epi32(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_srli_epi32(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_srli_epi32(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srli_epi32 + #define _mm256_srli_epi32(a, imm8) simde_mm256_srli_epi32(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srli_epi64 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + +#if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = a_.u64 >> SIMDE_CAST_VECTOR_SHIFT_COUNT(32, imm8); +#else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = a_.u64[i] >> imm8; + } +#endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_srli_epi64(a, imm8) _mm256_srli_epi64(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) +# define simde_mm256_srli_epi64(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_srli_epi64(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_srli_epi64(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srli_epi64 + #define _mm256_srli_epi64(a, imm8) simde_mm256_srli_epi64(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srli_si256 (simde__m256i a, const int imm8) + SIMDE_REQUIRE_CONSTANT_RANGE(imm8, 0, 255) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a); + + for (size_t h = 0 ; h < (sizeof(r_.m128i_private) / sizeof(r_.m128i_private[0])) ; h++) { + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.m128i_private[h].i8) / sizeof(r_.m128i_private[h].i8[0])) ; i++) { + const int e = imm8 + HEDLEY_STATIC_CAST(int, i); + r_.m128i_private[h].i8[i] = (e < 16) ? a_.m128i_private[h].i8[e] : 0; + } + } + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) +# define simde_mm256_srli_si256(a, imm8) _mm256_srli_si256(a, imm8) +#elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) && !defined(__PGI) +# define simde_mm256_srli_si256(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_srli_si128(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_srli_si128(simde_mm256_extracti128_si256(a, 0), (imm8))) +#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE) +# define simde_mm256_srli_si256(a, imm8) \ + simde_mm256_set_m128i( \ + simde_mm_bsrli_si128(simde_mm256_extracti128_si256(a, 1), (imm8)), \ + simde_mm_bsrli_si128(simde_mm256_extracti128_si256(a, 0), (imm8))) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srli_si256 + #define _mm256_srli_si256(a, imm8) simde_mm256_srli_si256(a, imm8) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srlv_epi32 (simde__m128i a, simde__m128i b) { + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + r_; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = HEDLEY_STATIC_CAST(__typeof__(r_.u32), (b_.u32 < 32) & (a_.u32 >> b_.u32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = (b_.u32[i] < 32) ? (a_.u32[i] >> b_.u32[i]) : 0; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_srlv_epi32(a, b) _mm_srlv_epi32(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_srlv_epi32 + #define _mm_srlv_epi32(a, b) simde_mm_srlv_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srlv_epi32 (simde__m256i a, simde__m256i b) { + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + r_; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u32 = HEDLEY_STATIC_CAST(__typeof__(r_.u32), (b_.u32 < 32) & (a_.u32 >> b_.u32)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = (b_.u32[i] < 32) ? (a_.u32[i] >> b_.u32[i]) : 0; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_srlv_epi32(a, b) _mm256_srlv_epi32(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srlv_epi32 + #define _mm256_srlv_epi32(a, b) simde_mm256_srlv_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m128i +simde_mm_srlv_epi64 (simde__m128i a, simde__m128i b) { + simde__m128i_private + a_ = simde__m128i_to_private(a), + b_ = simde__m128i_to_private(b), + r_; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = HEDLEY_STATIC_CAST(__typeof__(r_.u64), (b_.u64 < 64) & (a_.u64 >> b_.u64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = (b_.u64[i] < 64) ? (a_.u64[i] >> b_.u64[i]) : 0; + } + #endif + + return simde__m128i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm_srlv_epi64(a, b) _mm_srlv_epi64(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm_srlv_epi64 + #define _mm_srlv_epi64(a, b) simde_mm_srlv_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_srlv_epi64 (simde__m256i a, simde__m256i b) { + simde__m256i_private + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b), + r_; + + #if defined(SIMDE_VECTOR_SUBSCRIPT_SCALAR) + r_.u64 = HEDLEY_STATIC_CAST(__typeof__(r_.u64), (b_.u64 < 64) & (a_.u64 >> b_.u64)); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u64) / sizeof(r_.u64[0])) ; i++) { + r_.u64[i] = (b_.u64[i] < 64) ? (a_.u64[i] >> b_.u64[i]) : 0; + } + #endif + + return simde__m256i_from_private(r_); +} +#if defined(SIMDE_X86_AVX2_NATIVE) + #define simde_mm256_srlv_epi64(a, b) _mm256_srlv_epi64(a, b) +#endif +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_srlv_epi64 + #define _mm256_srlv_epi64(a, b) simde_mm256_srlv_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_stream_load_si256 (const simde__m256i* mem_addr) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_stream_load_si256(HEDLEY_CONST_CAST(simde__m256i*, mem_addr)); + #else + simde__m256i r; + simde_memcpy(&r, SIMDE_ALIGN_ASSUME_LIKE(mem_addr, simde__m256i), sizeof(r)); + return r; + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) +# define _mm256_stream_load_si256(mem_addr) simde_mm256_stream_load_si256(mem_addr) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sub_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sub_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sub_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sub_epi8(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i8 = a_.i8 - b_.i8; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = a_.i8[i] - b_.i8[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sub_epi8 + #define _mm256_sub_epi8(a, b) simde_mm256_sub_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sub_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sub_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sub_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sub_epi16(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i16 = a_.i16 - b_.i16; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = a_.i16[i] - b_.i16[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sub_epi16 + #define _mm256_sub_epi16(a, b) simde_mm256_sub_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_hsub_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_hsub_epi16(a, b); + #else + return simde_mm256_sub_epi16(simde_x_mm256_deinterleaveeven_epi16(a, b), simde_x_mm256_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_hsub_epi16 + #define _mm256_hsub_epi16(a, b) simde_mm256_hsub_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sub_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sub_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sub_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sub_epi32(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32 = a_.i32 - b_.i32; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i32) / sizeof(r_.i32[0])) ; i++) { + r_.i32[i] = a_.i32[i] - b_.i32[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sub_epi32 + #define _mm256_sub_epi32(a, b) simde_mm256_sub_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_hsub_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_hsub_epi32(a, b); + #else + return simde_mm256_sub_epi32(simde_x_mm256_deinterleaveeven_epi32(a, b), simde_x_mm256_deinterleaveodd_epi32(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_hsub_epi32 + #define _mm256_hsub_epi32(a, b) simde_mm256_hsub_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_sub_epi64 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_sub_epi64(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_sub_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_sub_epi64(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i64 = a_.i64 - b_.i64; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] - b_.i64[i]; + } + #endif + + return simde__m256i_from_private(r_); +#endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_sub_epi64 + #define _mm256_sub_epi64(a, b) simde_mm256_sub_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_x_mm256_sub_epu32 (simde__m256i a, simde__m256i b) { + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.u32 = a_.u32 - b_.u32; + #elif SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_x_mm_sub_epu32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_x_mm_sub_epu32(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u32) / sizeof(r_.u32[0])) ; i++) { + r_.u32[i] = a_.u32[i] - b_.u32[i]; + } + #endif + + return simde__m256i_from_private(r_); +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_subs_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_subs_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_subs_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_subs_epi8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i8) / sizeof(r_.i8[0])) ; i++) { + r_.i8[i] = simde_math_subs_i8(a_.i8[i], b_.i8[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_subs_epi8 + #define _mm256_subs_epi8(a, b) simde_mm256_subs_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_subs_epi16(simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_subs_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_subs_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_subs_epi16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i16) / sizeof(r_.i16[0])) ; i++) { + r_.i16[i] = simde_math_subs_i16(a_.i16[i], b_.i16[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_subs_epi16 + #define _mm256_subs_epi16(a, b) simde_mm256_subs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_hsubs_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_hsubs_epi16(a, b); + #else + return simde_mm256_subs_epi16(simde_x_mm256_deinterleaveeven_epi16(a, b), simde_x_mm256_deinterleaveodd_epi16(a, b)); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_hsubs_epi16 + #define _mm256_hsubs_epi16(a, b) simde_mm256_hsubs_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_subs_epu8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_subs_epu8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_subs_epu8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_subs_epu8(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u8) / sizeof(r_.u8[0])) ; i++) { + r_.u8[i] = simde_math_subs_u8(a_.u8[i], b_.u8[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_subs_epu8 + #define _mm256_subs_epu8(a, b) simde_mm256_subs_epu8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_subs_epu16(simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_subs_epu16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_subs_epu16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_subs_epu16(a_.m128i[1], b_.m128i[1]); + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.u16) / sizeof(r_.u16[0])) ; i++) { + r_.u16[i] = simde_math_subs_u16(a_.u16[i], b_.u16[i]); + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_subs_epu16 + #define _mm256_subs_epu16(a, b) simde_mm256_subs_epu16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +int +simde_x_mm256_test_all_ones (simde__m256i a) { + simde__m256i_private a_ = simde__m256i_to_private(a); + int r; + int_fast32_t r_ = ~HEDLEY_STATIC_CAST(int_fast32_t, 0); + + SIMDE_VECTORIZE_REDUCTION(&:r_) + for (size_t i = 0 ; i < (sizeof(a_.i32f) / sizeof(a_.i32f[0])) ; i++) { + r_ &= a_.i32f[i]; + } + + r = (r_ == ~HEDLEY_STATIC_CAST(int_fast32_t, 0)); + + return r; +} + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpacklo_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpacklo_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i8 = SIMDE_SHUFFLE_VECTOR_(8, 32, a_.i8, b_.i8, + 0, 32, 1, 33, 2, 34, 3, 35, + 4, 36, 5, 37, 6, 38, 7, 39, + 16, 48, 17, 49, 18, 50, 19, 51, + 20, 52, 21, 53, 22, 54, 23, 55); + #else + r_.m128i[0] = simde_mm_unpacklo_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpacklo_epi8(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpacklo_epi8 + #define _mm256_unpacklo_epi8(a, b) simde_mm256_unpacklo_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpacklo_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpacklo_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 =SIMDE_SHUFFLE_VECTOR_(16, 32, a_.i16, b_.i16, + 0, 16, 1, 17, 2, 18, 3, 19, 8, 24, 9, 25, 10, 26, 11, 27); + #else + r_.m128i[0] = simde_mm_unpacklo_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpacklo_epi16(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpacklo_epi16 + #define _mm256_unpacklo_epi16(a, b) simde_mm256_unpacklo_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpacklo_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpacklo_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.i32, b_.i32, + 0, 8, 1, 9, 4, 12, 5, 13); + #else + r_.m128i[0] = simde_mm_unpacklo_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpacklo_epi32(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpacklo_epi32 + #define _mm256_unpacklo_epi32(a, b) simde_mm256_unpacklo_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpacklo_epi64 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpacklo_epi64(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.i64, b_.i64, 0, 4, 2, 6); + #else + r_.m128i[0] = simde_mm_unpacklo_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpacklo_epi64(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpacklo_epi64 + #define _mm256_unpacklo_epi64(a, b) simde_mm256_unpacklo_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpackhi_epi8 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpackhi_epi8(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i8 = SIMDE_SHUFFLE_VECTOR_(8, 32, a_.i8, b_.i8, + 8, 40, 9, 41, 10, 42, 11, 43, + 12, 44, 13, 45, 14, 46, 15, 47, + 24, 56, 25, 57, 26, 58, 27, 59, + 28, 60, 29, 61, 30, 62, 31, 63); + #else + r_.m128i[0] = simde_mm_unpackhi_epi8(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpackhi_epi8(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpackhi_epi8 + #define _mm256_unpackhi_epi8(a, b) simde_mm256_unpackhi_epi8(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpackhi_epi16 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpackhi_epi16(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i16 = SIMDE_SHUFFLE_VECTOR_(16, 32, a_.i16, b_.i16, + 4, 20, 5, 21, 6, 22, 7, 23, + 12, 28, 13, 29, 14, 30, 15, 31); + #else + r_.m128i[0] = simde_mm_unpackhi_epi16(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpackhi_epi16(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpackhi_epi16 + #define _mm256_unpackhi_epi16(a, b) simde_mm256_unpackhi_epi16(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpackhi_epi32 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpackhi_epi32(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i32 = SIMDE_SHUFFLE_VECTOR_(32, 32, a_.i32, b_.i32, + 2, 10, 3, 11, 6, 14, 7, 15); + #else + r_.m128i[0] = simde_mm_unpackhi_epi32(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpackhi_epi32(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpackhi_epi32 + #define _mm256_unpackhi_epi32(a, b) simde_mm256_unpackhi_epi32(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_unpackhi_epi64 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_unpackhi_epi64(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if defined(SIMDE_SHUFFLE_VECTOR_) + r_.i64 = SIMDE_SHUFFLE_VECTOR_(64, 32, a_.i64, b_.i64, 1, 5, 3, 7); + #else + r_.m128i[0] = simde_mm_unpackhi_epi64(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_unpackhi_epi64(a_.m128i[1], b_.m128i[1]); + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_unpackhi_epi64 + #define _mm256_unpackhi_epi64(a, b) simde_mm256_unpackhi_epi64(a, b) +#endif + +SIMDE_FUNCTION_ATTRIBUTES +simde__m256i +simde_mm256_xor_si256 (simde__m256i a, simde__m256i b) { + #if defined(SIMDE_X86_AVX2_NATIVE) + return _mm256_xor_si256(a, b); + #else + simde__m256i_private + r_, + a_ = simde__m256i_to_private(a), + b_ = simde__m256i_to_private(b); + + #if SIMDE_NATURAL_VECTOR_SIZE_LE(128) + r_.m128i[0] = simde_mm_xor_si128(a_.m128i[0], b_.m128i[0]); + r_.m128i[1] = simde_mm_xor_si128(a_.m128i[1], b_.m128i[1]); + #elif defined(SIMDE_VECTOR_SUBSCRIPT_OPS) + r_.i32f = a_.i32f ^ b_.i32f; + #else + SIMDE_VECTORIZE + for (size_t i = 0 ; i < (sizeof(r_.i64) / sizeof(r_.i64[0])) ; i++) { + r_.i64[i] = a_.i64[i] ^ b_.i64[i]; + } + #endif + + return simde__m256i_from_private(r_); + #endif +} +#if defined(SIMDE_X86_AVX2_ENABLE_NATIVE_ALIASES) + #undef _mm256_xor_si256 + #define _mm256_xor_si256(a, b) simde_mm256_xor_si256(a, b) +#endif + +SIMDE_END_DECLS_ + +HEDLEY_DIAGNOSTIC_POP + +#endif /* !defined(SIMDE_X86_AVX2_H) */ +/* :: End ../simde/simde/x86/avx2.h :: */ diff --git a/source/outputSJ.cpp b/source/outputSJ.cpp index 750b4469..faf2558f 100644 --- a/source/outputSJ.cpp +++ b/source/outputSJ.cpp @@ -19,13 +19,10 @@ int compareUint(const void* i1, const void* i2) {//compare uint arrays void outputSJ(ReadAlignChunk** RAchunk, Parameters& P) {//collapses junctions from all therads/chunks; outputs junctions to file -// system("echo `date` ..... Writing splice junctions >> Log.timing.out"); - - - Junction oneSJ(RAchunk[0]->mapGen); + Junction oneSJ(RAchunk[0]->RA->genOut); char** sjChunks = new char* [P.runThreadN+1]; #define OUTSJ_limitScale 5 - OutSJ allSJ (P.limitOutSJcollapsed*OUTSJ_limitScale,P,RAchunk[0]->mapGen); + OutSJ allSJ (P.limitOutSJcollapsed*OUTSJ_limitScale,P,RAchunk[0]->RA->genOut); if (P.outFilterBySJoutStage!=1) {//chunkOutSJ for (int ic=0;ic ... STARsolo cell filtering ("calling") without remapping, followed by the path to raw count directory and output (filtered) prefix runThreadN 1 int: number of threads to run STAR @@ -53,9 +53,12 @@ genomeChainFiles - genomeFileSizes 0 uint(s)>0: genome files exact sizes in bytes. Typically, this should not be defined by the user. - -genomeConsensusFile - - string: VCF file with consensus SNPs (i.e. alternative allele is the major (AF>0.5) allele) + +genomeTransformOutput None + string(s) which output to transform back to original genome + SAM ... SAM/BAM alignments + SJ ... splice junctions (SJ.out.tab) + None ... no transformation of the output ### Genome Indexing Parameters - only used with --runMode genomeGenerate genomeChrBinNbits 18 @@ -69,6 +72,31 @@ genomeSAsparseD 1 genomeSuffixLengthMax -1 int: maximum length of the suffixes, has to be longer than read length. -1 = infinite. + +genomeTransformType None + string: type of genome transformation + None ... no transformation + Haploid ... replace reference alleles with alternative alleles from VCF file (e.g. consensus allele) + Diploid ... create two haplotypes for each chromosome listed in VCF file, for genotypes 1|2, assumes perfect phasing (e.g. personal genome) + +genomeTransformVCF - + string: path to VCF file for genome transformation + + + +#####UnderDevelopment_begin : not supported - do not use +genomeType Full + string: type of genome to generate + Full ... full (normal) genome + Transcriptome ... genome consists of transcript sequences + SuperTransriptome ... genome consists of superTranscript sequences +#####UnderDevelopment_end + +# DEPRECATED: please use --genomeTransformVCF and --genomeTransformType options instead. +#genomeConsensusFile - +# string: VCF file with consensus SNPs (i.e. alternative allele is the major (AF>0.5) allele) +# DEPRECATED + ### Splice Junctions Database @@ -100,16 +128,16 @@ sjdbOverhang 100 int>0: length of the donor/acceptor sequence on each side of the junctions, ideally = (mate_length - 1) sjdbScore 2 - int: extra alignment score for alignmets that cross database junctions + int: extra alignment score for alignments that cross database junctions sjdbInsertSave Basic string: which files to save when sjdb junctions are inserted on the fly at the mapping step - Basic ... only small junction / transcript files - All ... all files including big Genome, SA and SAindex - this will create a complete genome directory + Basic ... only small junction / transcript files + All ... all files including big Genome, SA and SAindex - this will create a complete genome directory ### Variation parameters varVCFfile - - string: path to the VCF file that contains variation data. + string: path to the VCF file that contains variation data. The 10th column should contain the genotype information, e.g. 0/1 ### Input Files inputBAMfile - @@ -121,13 +149,25 @@ readFilesType Fastx Fastx ... FASTA or FASTQ SAM SE ... SAM or BAM single-end reads; for BAM use --readFilesCommand samtools view SAM PE ... SAM or BAM paired-end reads; for BAM use --readFilesCommand samtools view + +readFilesSAMattrKeep All + string(s): for --readFilesType SAM SE/PE, which SAM tags to keep in the output BAM, e.g.: --readFilesSAMtagsKeep RG PL + All ... keep all tags + None ... do not keep any tags readFilesIn Read1 Read2 string(s): paths to files that contain input read1 (and, if needed, read2) +readFilesManifest - + string: path to the "manifest" file with the names of read files. The manifest file should contain 3 tab-separated columns: + paired-end reads: read1_file_name $tab$ read2_file_name $tab$ read_group_line. + single-end reads: read1_file_name $tab$ - $tab$ read_group_line. + Spaces, but not tabs are allowed in file names. + If read_group_line does not start with ID:, it can only contain one ID field, and ID: will be added to it. + If read_group_line starts with ID:, it can contain several fields separated by $tab$, and all fields will be be copied verbatim into SAM @RG header line. + readFilesPrefix - - string: preifx for the read files names, i.e. it will be added in front of the strings in --readFilesIn - -: no prefix + string: prefix for the read files names, i.e. it will be added in front of the strings in --readFilesIn readFilesCommand - string(s): command line to execute for each of the input file. This command should generate FASTA or FASTQ text and send it to stdout @@ -143,27 +183,49 @@ readMatesLengthsIn NotEqual readNameSeparator / string(s): character(s) separating the part of the read names that will be trimmed in output (read name after space is always trimmed) +readQualityScoreBase 33 + int>=0: number to be subtracted from the ASCII code to get Phred quality score + +### Read Clipping + +clipAdapterType Hamming + string: adapter clipping type + Hamming ... adapter clipping based on Hamming distance, with the number of mismatches controlled by --clip5pAdapterMMp + CellRanger4 ... 5p and 3p adapter clipping similar to CellRanger4. Utilizes Opal package by Martin Šošić: https://github.com/Martinsos/opal + None ... no adapter clipping, all other clip* parameters are disregarded + clip3pNbases 0 int(s): number(s) of bases to clip from 3p of each mate. If one value is given, it will be assumed the same for both mates. -clip5pNbases 0 - int(s): number(s) of bases to clip from 5p of each mate. If one value is given, it will be assumed the same for both mates. - clip3pAdapterSeq - string(s): adapter sequences to clip from 3p of each mate. If one value is given, it will be assumed the same for both mates. + polyA ... polyA sequence with the length equal to read length clip3pAdapterMMp 0.1 - double(s): max proportion of mismatches for 3p adpater clipping for each mate. If one value is given, it will be assumed the same for both mates. + double(s): max proportion of mismatches for 3p adapter clipping for each mate. If one value is given, it will be assumed the same for both mates. clip3pAfterAdapterNbases 0 int(s): number of bases to clip from 3p of each mate after the adapter clipping. If one value is given, it will be assumed the same for both mates. +clip5pNbases 0 + int(s): number(s) of bases to clip from 5p of each mate. If one value is given, it will be assumed the same for both mates. + +#####UnderDevelopment_begin : not supported - do not use +clip5pAdapterSeq - + string(s): adapter sequences to clip from 5p of each mate, separated by space. + +clip5pAdapterMMp 0.1 + double(s): max proportion of mismatches for 5p adapter clipping for each mate, separated by space + +clip5pAfterAdapterNbases 0 + int(s): number of bases to clip from 5p of each mate after the adapter clipping, separated by space. +#####UnderDevelopment_end ### Limits limitGenomeGenerateRAM 31000000000 int>0: maximum available RAM (bytes) for genome generation -limitIObufferSize 150000000 +limitIObufferSize 30000000 50000000 int>0: max available buffers size (bytes) for input/output, per thread limitOutSAMoneReadBytes 100000 @@ -202,7 +264,7 @@ outStd Log Log ... log messages SAM ... alignments in SAM format (which normally are output to Aligned.out.sam file), normal standard output will go into Log.std.out BAM_Unsorted ... alignments in BAM format, unsorted. Requires --outSAMtype BAM Unsorted - BAM_SortedByCoordinate ... alignments in BAM format, unsorted. Requires --outSAMtype BAM SortedByCoordinate + BAM_SortedByCoordinate ... alignments in BAM format, sorted by coordinate. Requires --outSAMtype BAM SortedByCoordinate BAM_Quant ... alignments to transcriptome in BAM format, unsorted. Requires --quantMode TranscriptomeSAM outReadsUnmapped None @@ -235,24 +297,46 @@ outSAMmode Full Full ... full SAM output NoQS ... full SAM but without quality scores -outSAMstrandField None +outSAMstrandField None string: Cufflinks-like strand field flag None ... not used - intronMotif ... strand derived from the intron motif. Reads with inconsistent and/or non-canonical introns are filtered out. + intronMotif ... strand derived from the intron motif. This option changes the output alignments: reads with inconsistent and/or non-canonical introns are filtered out. outSAMattributes Standard - string: a string of desired SAM attributes, in the order desired for the output SAM - NH HI AS nM NM MD jM jI XS MC ch ... any combination in any order + string: a string of desired SAM attributes, in the order desired for the output SAM. Tags can be listed in any combination/order. + ***Presets: None ... no attributes Standard ... NH HI AS nM - All ... NH HI AS nM NM MD jM jI MC ch + All ... NH HI AS nM NM MD jM jI MC ch + ***Alignment: + NH ... number of loci the reads maps to: =1 for unique mappers, >1 for multimappers. Standard SAM tag. + HI ... multiple alignment index, starts with --outSAMattrIHstart (=1 by default). Standard SAM tag. + AS ... local alignment score, +1/-1 for matches/mismateches, score* penalties for indels and gaps. For PE reads, total score for two mates. Stadnard SAM tag. + nM ... number of mismatches. For PE reads, sum over two mates. + NM ... edit distance to the reference (number of mismatched + inserted + deleted bases) for each mate. Standard SAM tag. + MD ... string encoding mismatched and deleted reference bases (see standard SAM specifications). Standard SAM tag. + jM ... intron motifs for all junctions (i.e. N in CIGAR): 0: non-canonical; 1: GT/AG, 2: CT/AC, 3: GC/AG, 4: CT/GC, 5: AT/AC, 6: GT/AT. If splice junctions database is used, and a junction is annotated, 20 is added to its motif value. + jI ... start and end of introns for all junctions (1-based). + XS ... alignment strand according to --outSAMstrandField. + MC ... mate's CIGAR string. Standard SAM tag. + ch ... marks all segment of all chimeric alingments for --chimOutType WithinBAM output. + cN ... number of bases clipped from the read ends: 5' and 3' + ***Variation: vA ... variant allele - vG ... genomic coordiante of the variant overlapped by the read - vW ... 0/1 - alignment does not pass / passes WASP filtering. Requires --waspOutputMode SAMtag - CR CY UR UY ... sequences and quality scores of cell barcodes and UMIs for the solo* demultiplexing - Unsupported/undocumented: - rB ... alignment block read/genomic coordinates - vR ... read coordinate of the variant + vG ... genomic coordinate of the variant overlapped by the read. + vW ... 1 - alignment passes WASP filtering; 2,3,4,5,6,7 - alignment does not pass WASP filtering. Requires --waspOutputMode SAMtag. + ***STARsolo: + CR CY UR UY ... sequences and quality scores of cell barcodes and UMIs for the solo* demultiplexing. + GX GN ... gene ID and gene name for unique-gene reads. + gx gn ... gene IDs and gene names for unique- and multi-gene reads. + CB UB ... error-corrected cell barcodes and UMIs for solo* demultiplexing. Requires --outSAMtype BAM SortedByCoordinate. + sM ... assessment of CB and UMI. + sS ... sequence of the entire barcode (CB,UMI,adapter). + sQ ... quality of the entire barcode. + ***Unsupported/undocumented: + ha ... haplotype (1/2) when mapping to the diploid genome. Requires genome generated with --genomeTransformType Diploid . + rB ... alignment block read/genomic coordinates. + vR ... read coordinate of the variant. outSAMattrIHstart 1 int>=0: start value for the IH attribute. 0 may be required by some downstream software, such as Cufflinks or StringTie. @@ -270,12 +354,12 @@ outSAMorder Paired Paired: one mate after the other for all paired alignments PairedKeepInputOrder: one mate after the other for all paired alignments, the order is kept the same as in the input FASTQ files -outSAMprimaryFlag OneBestScore +outSAMprimaryFlag OneBestScore string: which alignments are considered primary - all others will be marked with 0x100 bit in the FLAG OneBestScore ... only one alignment with the best score is primary AllBestScore ... all alignments with the best score are primary -outSAMreadID Standard +outSAMreadID Standard string: read ID record type Standard ... first word (until space) from the FASTx read ID line, removing /1,/2 from the end Number ... read number (index) in the FASTx file @@ -311,7 +395,7 @@ outSAMfilter None outSAMmultNmax -1 - int: max number of multiple alignments for a read that will be output to the SAM/BAM files. + int: max number of multiple alignments for a read that will be output to the SAM/BAM files. Note that if this value is not equal to -1, the top scoring alignment will be output first -1 ... all alignments (up to --outFilterMultimapNmax) will be output outSAMtlen 1 @@ -399,20 +483,26 @@ outFilterMatchNminOverLread 0.66 outFilterIntronMotifs None string: filter alignment using their motifs - None ... no filtering - RemoveNoncanonical ... filter out alignments that contain non-canonical junctions - RemoveNoncanonicalUnannotated ... filter out alignments that contain non-canonical unannotated junctions when using annotated splice junctions database. The annotated non-canonical junctions will be kept. + None ... no filtering + RemoveNoncanonical ... filter out alignments that contain non-canonical junctions + RemoveNoncanonicalUnannotated ... filter out alignments that contain non-canonical unannotated junctions when using annotated splice junctions database. The annotated non-canonical junctions will be kept. outFilterIntronStrands RemoveInconsistentStrands string: filter alignments RemoveInconsistentStrands ... remove alignments that have junctions with inconsistent strands None ... no filtering +### Output splice junctions (SJ.out.tab) +outSJtype Standard + string: type of splice junction output + Standard ... standard SJ.out.tab output + None ... no splice junction output + ### Output Filtering: Splice Junctions outSJfilterReads All string: which reads to consider for collapsed splice junctions output - All: all reads, unique- and multi-mappers - Unique: uniquely mapping reads only + All ... all reads, unique- and multi-mappers + Unique ... uniquely mapping reads only outSJfilterOverhangMin 30 12 12 12 4 integers: minimum overhang length for splice junctions on both sides for: (1) non-canonical motifs, (2) GT/AG and CT/AC motif, (3) GC/AG and CT/GC motif, (4) AT/AC and GT/AT motif. -1 means no output for that motif @@ -466,7 +556,7 @@ scoreInsBase -2 insertion extension penalty per base (in addition to scoreInsOpen) scoreStitchSJshift 1 - maximum score reduction while searching for SJ boundaries inthe stitching step + maximum score reduction while searching for SJ boundaries in the stitching step ### Alignments and Seeding @@ -478,7 +568,7 @@ seedSearchStartLmaxOverLread 1.0 real: seedSearchStartLmax normalized to read length (sum of mates' lengths for paired-end reads) seedSearchLmax 0 - int>=0: defines the maximum length of the seeds, if =0 max seed lengthis infinite + int>=0: defines the maximum length of the seeds, if =0 seed length is not limited seedMultimapNmax 10000 int>0: only pieces that map fewer than this value are utilized in the stitching procedure @@ -495,6 +585,9 @@ seedNoneLociPerWindow 10 seedSplitMin 12 int>0: min length of the seed sequences split by Ns or mate gap +seedMapMin 5 + int>0: min length of seeds to be mapped + alignIntronMin 21 minimum intron size: genomic gap is considered intron if its length>=alignIntronMin, otherwise it is considered Deletion @@ -586,7 +679,7 @@ chimOutType Junctions Junctions ... Chimeric.out.junction SeparateSAMold ... output old SAM into separate Chimeric.out.sam file WithinBAM ... output into main aligned BAM files (Aligned.*.bam) - WithinBAM HardClip ... (default) hard-clipping in the CIGAR for supplemental chimeric alignments (defaultif no 2nd word is present) + WithinBAM HardClip ... (default) hard-clipping in the CIGAR for supplemental chimeric alignments (default if no 2nd word is present) WithinBAM SoftClip ... soft-clipping in the CIGAR for supplemental chimeric alignments chimSegmentMin 0 @@ -626,12 +719,12 @@ chimMultimapScoreRange 1 int>=0: the score range for multi-mapping chimeras below the best chimeric score. Only works with --chimMultimapNmax > 1 chimNonchimScoreDropMin 20 - int>=0: to trigger chimeric detection, the drop in the best non-chimeric alignment score with respect to the read length has to be smaller than this value + int>=0: to trigger chimeric detection, the drop in the best non-chimeric alignment score with respect to the read length has to be greater than this value chimOutJunctionFormat 0 int: formatting type for the Chimeric.out.junction file 0 ... no comment lines/headers - 1 ... comment lines at the end of the file: command line and Nreads: total, unique, multi + 1 ... comment lines at the end of the file: command line and Nreads: total, unique/multi-mapping ### Quantification of Annotations quantMode - @@ -664,16 +757,20 @@ twopass1readsN -1 ### WASP parameters waspOutputMode None - string: WASP allele-specific output type. This is re-implemenation of the original WASP mappability filtering by Bryce van de Geijn, Graham McVicker, Yoav Gilad & Jonathan K Pritchard. Please cite the original WASP paper: Nature Methods 12, 1061–1063 (2015), https://www.nature.com/articles/nmeth.3582 . + string: WASP allele-specific output type. This is re-implementation of the original WASP mappability filtering by Bryce van de Geijn, Graham McVicker, Yoav Gilad & Jonathan K Pritchard. Please cite the original WASP paper: Nature Methods 12, 1061–1063 (2015), https://www.nature.com/articles/nmeth.3582 . SAMtag ... add WASP tags to the alignments that pass WASP filtering ### STARsolo (single cell RNA-seq) parameters soloType None string(s): type of single-cell RNA-seq - Droplet ... one cell barcode and one UMI barcode in read2, e.g. Drop-seq and 10X Chromium + CB_UMI_Simple ... (a.k.a. Droplet) one UMI and one Cell Barcode of fixed length in read2, e.g. Drop-seq and 10X Chromium. + CB_UMI_Complex ... multiple Cell Barcodes of varying length, one UMI of fixed length and one adapter sequence of fixed length are allowed in read2 only (e.g. inDrop, ddSeq). + CB_samTagOut ... output Cell Barcode as CR and/or CB SAm tag. No UMI counting. --readFilesIn cDNA_read1 [cDNA_read2 if paired-end] CellBarcode_read . Requires --outSAMtype BAM Unsorted [and/or SortedByCoordinate] + SmartSeq ... Smart-seq: each cell in a separate FASTQ (paired- or single-end), barcodes are corresponding read-groups, no UMI sequences, alignments deduplicated according to alignment start and end (after extending soft-clipped bases) soloCBwhitelist - - string: file with whitelist of cell barcodes + string(s): file(s) with whitelist(s) of cell barcodes. Only --soloType CB_UMI_Complex allows more than one whitelist file. + None ... no whitelist: all cell barcodes are allowed soloCBstart 1 int>0: cell barcode start base @@ -690,7 +787,54 @@ soloUMIlen 10 soloBarcodeReadLength 1 int: length of the barcode read 1 ... equal to sum of soloCBlen+soloUMIlen - 0 ... not defined, do not check + 0 ... not defined, do not check + +soloBarcodeMate 0 + int: identifies which read mate contains the barcode (CB+UMI) sequence + 0 ... barcode sequence is on separate read, which should always be the last file in the --readFilesIn listed + 1 ... barcode sequence is a part of mate 1 + 2 ... barcode sequence is a part of mate 2 + +soloCBposition - + strings(s) position of Cell Barcode(s) on the barcode read. + Presently only works with --soloType CB_UMI_Complex, and barcodes are assumed to be on Read2. + Format for each barcode: startAnchor_startPosition_endAnchor_endPosition + start(end)Anchor defines the Anchor Base for the CB: 0: read start; 1: read end; 2: adapter start; 3: adapter end + start(end)Position is the 0-based position with of the CB start(end) with respect to the Anchor Base + String for different barcodes are separated by space. + Example: inDrop (Zilionis et al, Nat. Protocols, 2017): + --soloCBposition 0_0_2_-1 3_1_3_8 + +soloUMIposition - + string position of the UMI on the barcode read, same as soloCBposition + Example: inDrop (Zilionis et al, Nat. Protocols, 2017): + --soloCBposition 3_9_3_14 + +soloAdapterSequence - + string: adapter sequence to anchor barcodes. Only one adapter sequence is allowed. + +soloAdapterMismatchesNmax 1 + int>0: maximum number of mismatches allowed in adapter sequence. + +soloCBmatchWLtype 1MM_multi + string: matching the Cell Barcodes to the WhiteList + Exact ... only exact matches allowed + 1MM ... only one match in whitelist with 1 mismatched base allowed. Allowed CBs have to have at least one read with exact match. + 1MM_multi ... multiple matches in whitelist with 1 mismatched base allowed, posterior probability calculation is used choose one of the matches. + Allowed CBs have to have at least one read with exact match. This option matches best with CellRanger 2.2.0 + 1MM_multi_pseudocounts ... same as 1MM_Multi, but pseudocounts of 1 are added to all whitelist barcodes. + 1MM_multi_Nbase_pseudocounts ... same as 1MM_multi_pseudocounts, multimatching to WL is allowed for CBs with N-bases. This option matches best with CellRanger >= 3.0.0 + ParseBio_ED3 ... allow up to edit distance of 3 fpr each of the barcodes. May include one deletion + one insertion. Only works with --soloType CB_UMI_Complex. Matches to multiple passlist barcdoes are not allowed. Similar to ParseBio Split-seq pipeline. + +soloInputSAMattrBarcodeSeq - + string(s): when inputting reads from a SAM file (--readsFileType SAM SE/PE), these SAM attributes mark the barcode sequence (in proper order). + For instance, for 10X CellRanger or STARsolo BAMs, use --soloInputSAMattrBarcodeSeq CR UR . + This parameter is required when running STARsolo with input from SAM. + +soloInputSAMattrBarcodeQual - + string(s): when inputting reads from a SAM file (--readsFileType SAM SE/PE), these SAM attributes mark the barcode qualities (in proper order). + For instance, for 10X CellRanger or STARsolo BAMs, use --soloInputSAMattrBarcodeQual CY UY . + If this parameter is '-' (default), the quality 'H' will be assigned to all bases. soloStrand Forward string: strandedness of the solo libraries: @@ -699,23 +843,61 @@ soloStrand Forward Reverse ... read strand opposite to the original RNA molecule soloFeatures Gene - string(s): genomic features for which the UMI counts per Cell Barcode are collected + string(s): genomic features for which the UMI counts per Cell Barcode are collected Gene ... genes: reads match the gene transcript SJ ... splice junctions: reported in SJ.out.tab - GeneFull ... full genes: count all reads overlapping genes' exons and introns + GeneFull ... full gene (pre-mRNA): count all reads overlapping genes' exons and introns + GeneFull_ExonOverIntron ... full gene (pre-mRNA): count all reads overlapping genes' exons and introns: prioritize 100% overlap with exons + GeneFull_Ex50pAS ... full gene (pre-RNA): count all reads overlapping genes' exons and introns: prioritize >50% overlap with exons. Do not count reads with 100% exonic overlap in the antisense direction. + +#####UnderDevelopment_begin : not supported - do not use + Transcript3p ... quantification of transcript for 3' protocols +#####UnderDevelopment_end + +soloMultiMappers Unique + string(s): counting method for reads mapping to multiple genes + Unique ... count only reads that map to unique genes + Uniform ... uniformly distribute multi-genic UMIs to all genes + Rescue ... distribute UMIs proportionally to unique+uniform counts (~ first iteration of EM) + PropUnique ... distribute UMIs proportionally to unique mappers, if present, and uniformly if not. + EM ... multi-gene UMIs are distributed using Expectation Maximization algorithm soloUMIdedup 1MM_All string(s): type of UMI deduplication (collapsing) algorithm - 1MM_All ... all UMIs with 1 mismatch distance to each other are collapsed (i.e. counted once) - 1MM_Directional ... follows the "directional" method from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017). - 1MM_NotCollapsed ... UMIs with 1 mismatch distance to others are not collapsed (i.e. all counted) - -soloOutFileNames Solo.out/ genes.tsv barcodes.tsv matrix.mtx matrixSJ.mtx matrixGeneFull.mtx - string(s) file names for STARsolo output - 1st word ... file name prefix - 2nd word ... gene IDs and names - 3rd word ... barcode sequences - 4th word ... cell/Gene counts matrix - 5th word ... cell/SJ counts matrix - 6th word ... cell/GeneFull counts matrix - + 1MM_All ... all UMIs with 1 mismatch distance to each other are collapsed (i.e. counted once). + 1MM_Directional_UMItools ... follows the "directional" method from the UMI-tools by Smith, Heger and Sudbery (Genome Research 2017). + 1MM_Directional ... same as 1MM_Directional_UMItools, but with more stringent criteria for duplicate UMIs + Exact ... only exactly matching UMIs are collapsed. + NoDedup ... no deduplication of UMIs, count all reads. + 1MM_CR ... CellRanger2-4 algorithm for 1MM UMI collapsing. + +soloUMIfiltering - + string(s) type of UMI filtering (for reads uniquely mapping to genes) + - ... basic filtering: remove UMIs with N and homopolymers (similar to CellRanger 2.2.0). + MultiGeneUMI ... basic + remove lower-count UMIs that map to more than one gene. + MultiGeneUMI_All ... basic + remove all UMIs that map to more than one gene. + MultiGeneUMI_CR ... basic + remove lower-count UMIs that map to more than one gene, matching CellRanger > 3.0.0 . + Only works with --soloUMIdedup 1MM_CR + +soloOutFileNames Solo.out/ features.tsv barcodes.tsv matrix.mtx + string(s) file names for STARsolo output: + file_name_prefix gene_names barcode_sequences cell_feature_count_matrix + +soloCellFilter CellRanger2.2 3000 0.99 10 + string(s): cell filtering type and parameters + None ... do not output filtered cells + TopCells ... only report top cells by UMI count, followed by the exact number of cells + CellRanger2.2 ... simple filtering of CellRanger 2.2. + Can be followed by numbers: number of expected cells, robust maximum percentile for UMI count, maximum to minimum ratio for UMI count + The harcoded values are from CellRanger: nExpectedCells=3000; maxPercentile=0.99; maxMinRatio=10 + EmptyDrops_CR ... EmptyDrops filtering in CellRanger flavor. Please cite the original EmptyDrops paper: A.T.L Lun et al, Genome Biology, 20, 63 (2019): https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1662-y + Can be followed by 10 numeric parameters: nExpectedCells maxPercentile maxMinRatio indMin indMax umiMin umiMinFracMedian candMaxN FDR simN + The harcoded values are from CellRanger: 3000 0.99 10 45000 90000 500 0.01 20000 0.01 10000 + +soloOutFormatFeaturesGeneField3 "Gene Expression" + string(s): field 3 in the Gene features.tsv file. If "-", then no 3rd field is output. + +#####UnderDevelopment_begin : not supported - do not use +soloClusterCBfile - + string: file containing the cluster information for cell barcodes, two columns: CB cluster_index. Only used with --soloFeatures Transcript3p +#####UnderDevelopment_end diff --git a/source/parametersDefault.xxd b/source/parametersDefault.xxd index ddc09a35..148b53a1 100644 --- a/source/parametersDefault.xxd +++ b/source/parametersDefault.xxd @@ -2,7 +2,7 @@ unsigned char parametersDefault[] = { 0x23, 0x23, 0x23, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x32, 0x2e, 0x37, 0x2e, 0x31, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x32, 0x2e, 0x37, 0x2e, 0x34, 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, @@ -54,221 +54,258 @@ unsigned char parametersDefault[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x2e, 0x0a, 0x0a, 0x20, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, - 0x65, 0x61, 0x64, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x70, - 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x41, 0x4d, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, - 0x20, 0x42, 0x41, 0x4d, 0x2e, 0x20, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, - 0x74, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x77, 0x6f, 0x72, - 0x6b, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x6f, 0x75, - 0x74, 0x57, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x6d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x66, 0x74, - 0x4f, 0x76, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, - 0x69, 0x66, 0x74, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, - 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x28, 0x2d, - 0x2d, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x66, 0x69, 0x6c, 0x65, - 0x29, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x67, 0x65, - 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, - 0x69, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x29, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, - 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, 0x65, + 0x61, 0x64, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x70, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x42, 0x41, 0x4d, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x42, 0x41, 0x4d, 0x2e, 0x20, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, + 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, + 0x57, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x2d, 0x2d, 0x62, 0x61, 0x6d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, + 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x2d, 0x6f, + 0x76, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x20, 0x28, 0x2d, 0x2d, 0x73, 0x6a, 0x64, 0x62, + 0x47, 0x54, 0x46, 0x66, 0x69, 0x6c, 0x65, 0x29, 0x20, 0x62, 0x65, 0x74, + 0x77, 0x65, 0x65, 0x6e, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, + 0x61, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x75, + 0x73, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x28, 0x73, 0x29, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x65, 0x6c, 0x6c, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x3c, + 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x74, 0x6f, 0x2f, 0x72, 0x61, 0x77, + 0x2f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x64, 0x69, 0x72, 0x2f, 0x3e, + 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x74, 0x6f, + 0x2f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2f, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x3e, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x53, + 0x54, 0x41, 0x52, 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x63, 0x65, 0x6c, 0x6c, + 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x28, + 0x22, 0x63, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0x29, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, + 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61, 0x77, 0x20, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x28, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x29, 0x20, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x54, + 0x68, 0x72, 0x65, 0x61, 0x64, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, - 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x53, 0x54, - 0x41, 0x52, 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x44, 0x69, 0x72, 0x50, 0x65, - 0x72, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x55, 0x73, 0x65, 0x72, 0x5f, 0x52, 0x57, 0x58, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x69, 0x65, 0x73, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x2d, - 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x55, 0x73, 0x65, 0x72, 0x5f, 0x52, 0x57, 0x58, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x61, 0x64, - 0x2f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, - 0x6c, 0x6c, 0x5f, 0x52, 0x57, 0x58, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x61, 0x6c, 0x6c, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x2f, 0x77, 0x72, 0x69, - 0x74, 0x65, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x28, - 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x63, 0x68, 0x6d, 0x6f, - 0x64, 0x20, 0x37, 0x37, 0x37, 0x29, 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x52, - 0x4e, 0x47, 0x73, 0x65, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x37, 0x37, 0x37, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x2e, 0x0a, 0x0a, - 0x0a, 0x23, 0x23, 0x23, 0x20, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x0a, 0x67, - 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x44, 0x69, 0x72, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2e, 0x2f, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x44, - 0x69, 0x72, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x79, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, - 0x6d, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, - 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x28, 0x66, 0x6f, 0x72, - 0x20, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x73, 0x29, 0x20, 0x6f, - 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x28, 0x66, 0x6f, 0x72, - 0x20, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x47, 0x65, 0x6e, 0x6f, 0x6d, - 0x65, 0x29, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x4c, 0x6f, - 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x53, 0x68, 0x61, 0x72, - 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6d, 0x6f, 0x64, - 0x65, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, - 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x75, 0x73, 0x61, 0x67, 0x65, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, - 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x20, 0x4f, - 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, - 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4c, 0x6f, 0x61, 0x64, 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x65, - 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x6f, - 0x61, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, - 0x74, 0x6f, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x20, 0x69, 0x6e, - 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x61, 0x66, 0x74, 0x65, - 0x72, 0x20, 0x72, 0x75, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, + 0x72, 0x75, 0x6e, 0x20, 0x53, 0x54, 0x41, 0x52, 0x0a, 0x0a, 0x72, 0x75, + 0x6e, 0x44, 0x69, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x73, 0x65, 0x72, 0x5f, 0x52, + 0x57, 0x58, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x75, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x73, 0x65, 0x72, + 0x5f, 0x52, 0x57, 0x58, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x75, 0x73, 0x65, + 0x72, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x2f, 0x77, 0x72, 0x69, 0x74, 0x65, + 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x5f, 0x52, 0x57, 0x58, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x2d, 0x72, 0x65, + 0x61, 0x64, 0x2f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x2f, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x20, 0x28, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, + 0x73, 0x20, 0x63, 0x68, 0x6d, 0x6f, 0x64, 0x20, 0x37, 0x37, 0x37, 0x29, + 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x52, 0x4e, 0x47, 0x73, 0x65, 0x65, 0x64, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x37, 0x37, + 0x37, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x72, + 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x73, + 0x65, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x47, + 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x44, + 0x69, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2f, 0x47, + 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x44, 0x69, 0x72, 0x2f, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x61, + 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x77, 0x68, 0x65, 0x72, + 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x64, 0x20, 0x28, 0x66, 0x6f, 0x72, 0x20, 0x2d, 0x2d, 0x72, 0x75, 0x6e, + 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, 0x65, + 0x61, 0x64, 0x73, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x28, 0x66, 0x6f, 0x72, 0x20, 0x2d, 0x2d, 0x72, 0x75, 0x6e, + 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x29, 0x0a, 0x0a, 0x67, 0x65, + 0x6e, 0x6f, 0x6d, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x20, 0x75, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, + 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x72, 0x75, + 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, + 0x65, 0x61, 0x64, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x6f, 0x61, 0x64, - 0x41, 0x6e, 0x64, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x20, 0x20, + 0x41, 0x6e, 0x64, 0x4b, 0x65, 0x65, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x64, 0x20, 0x62, 0x75, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, - 0x72, 0x75, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x6f, 0x61, 0x64, 0x41, 0x6e, - 0x64, 0x45, 0x78, 0x69, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, - 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x64, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x65, 0x78, 0x69, 0x74, 0x2c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, - 0x65, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x72, - 0x75, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x70, - 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x6a, - 0x75, 0x73, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6c, - 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, - 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x65, 0x70, + 0x20, 0x69, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, + 0x79, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x72, 0x75, 0x6e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4c, 0x6f, 0x61, 0x64, 0x41, 0x6e, 0x64, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x6f, + 0x61, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, + 0x74, 0x6f, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x62, 0x75, + 0x74, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, + 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x72, 0x75, 0x6e, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4c, 0x6f, 0x61, 0x64, 0x41, 0x6e, 0x64, 0x45, 0x78, 0x69, 0x74, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x6f, 0x61, 0x64, + 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, + 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x78, 0x69, 0x74, 0x2c, + 0x20, 0x6b, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x6d, + 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x75, + 0x74, 0x75, 0x72, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x73, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, 0x6f, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, + 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x20, + 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x53, + 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x6d, + 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, + 0x6a, 0x6f, 0x62, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, + 0x65, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x70, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, + 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x46, 0x61, 0x73, 0x74, + 0x61, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x70, + 0x61, 0x74, 0x68, 0x28, 0x73, 0x29, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x66, 0x61, 0x73, 0x74, 0x61, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, + 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x2e, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, + 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x46, + 0x41, 0x53, 0x54, 0x41, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, + 0x74, 0x68, 0x65, 0x79, 0x20, 0x2a, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x2a, 0x20, 0x62, 0x65, 0x20, 0x7a, 0x69, 0x70, 0x70, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4d, - 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, - 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, - 0x61, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2c, - 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x69, 0x74, 0x73, 0x20, - 0x6f, 0x77, 0x6e, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, - 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, - 0x6d, 0x65, 0x46, 0x61, 0x73, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, + 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, + 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x29, 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, + 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x20, 0x28, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, + 0x64, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x61, 0x64, + 0x73, 0x29, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x20, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x20, 0x28, 0x6e, 0x65, 0x77, 0x29, 0x20, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x28, 0x65, + 0x2e, 0x67, 0x2e, 0x20, 0x73, 0x70, 0x69, 0x6b, 0x65, 0x2d, 0x69, 0x6e, + 0x73, 0x29, 0x2e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x6c, + 0x69, 0x66, 0x74, 0x6f, 0x76, 0x65, 0x72, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, + 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x6c, 0x69, + 0x66, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x20, 0x2e, 0x0a, 0x0a, 0x67, 0x65, + 0x6e, 0x6f, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, + 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x69, 0x6e, 0x74, + 0x28, 0x73, 0x29, 0x3e, 0x30, 0x3a, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, + 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x65, 0x78, 0x61, 0x63, + 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x54, 0x79, 0x70, 0x69, 0x63, 0x61, + 0x6c, 0x6c, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x28, 0x73, 0x29, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x28, 0x73, 0x29, - 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x73, 0x74, - 0x61, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, - 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x73, - 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x73, - 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, - 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, - 0x74, 0x65, 0x78, 0x74, 0x20, 0x46, 0x41, 0x53, 0x54, 0x41, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x2a, - 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x2a, 0x20, 0x62, 0x65, 0x20, 0x7a, - 0x69, 0x70, 0x70, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x6f, + 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x67, 0x65, + 0x6e, 0x6f, 0x6d, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x2d, - 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, - 0x6f, 0x6d, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x29, - 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, - 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x2d, - 0x2d, 0x72, 0x75, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x73, 0x29, 0x20, 0x74, 0x6f, 0x20, - 0x61, 0x64, 0x64, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x28, 0x6e, - 0x65, 0x77, 0x29, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, - 0x6f, 0x6d, 0x65, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x73, 0x70, - 0x69, 0x6b, 0x65, 0x2d, 0x69, 0x6e, 0x73, 0x29, 0x2e, 0x0a, 0x0a, 0x67, - 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x6f, 0x76, 0x65, - 0x72, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x4d, - 0x6f, 0x64, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x4f, 0x76, 0x65, 0x72, - 0x20, 0x2e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x46, 0x69, - 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x28, 0x73, 0x29, 0x3e, 0x30, 0x3a, - 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, 0x20, 0x73, 0x69, 0x7a, 0x65, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2e, 0x20, - 0x54, 0x79, 0x70, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x2c, 0x20, 0x74, - 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x43, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x56, 0x43, - 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x20, 0x53, 0x4e, - 0x50, 0x73, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x61, 0x6c, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c, - 0x65, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, - 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x28, 0x41, 0x46, 0x3e, 0x30, 0x2e, 0x35, - 0x29, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x29, 0x0a, 0x0a, 0x23, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x53, 0x41, 0x4d, + 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x70, 0x6c, 0x69, + 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x28, 0x53, 0x4a, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x74, 0x61, 0x62, + 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x20, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x2d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, @@ -351,124 +388,223 @@ unsigned char parametersDefault[] = { 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2e, 0x20, 0x2d, 0x31, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x53, - 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x20, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x68, 0x72, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x70, 0x61, - 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x61, 0x74, 0x65, 0x73, 0x20, 0x28, 0x63, 0x68, 0x72, 0x20, 0x3c, 0x74, - 0x61, 0x62, 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x3c, 0x74, - 0x61, 0x62, 0x3e, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x3c, 0x74, 0x61, 0x62, - 0x3e, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x29, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, - 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, - 0x74, 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x4d, 0x75, 0x6c, 0x74, 0x69, - 0x70, 0x6c, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x63, 0x61, - 0x6e, 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, - 0x64, 0x20, 0x77, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, - 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x6e, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, - 0x46, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x74, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x67, 0x65, + 0x6e, 0x6f, 0x6d, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, + 0x6d, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, + 0x6f, 0x66, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x61, 0x70, 0x6c, 0x6f, 0x69, + 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x70, + 0x6c, 0x61, 0x63, 0x65, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x73, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, + 0x69, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x73, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x56, 0x43, 0x46, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, + 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x69, 0x70, 0x6c, 0x6f, 0x69, + 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x68, 0x61, 0x70, 0x6c, + 0x6f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, + 0x61, 0x63, 0x68, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x6f, 0x73, 0x6f, + 0x6d, 0x65, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, + 0x20, 0x56, 0x43, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x20, 0x31, 0x7c, 0x32, 0x2c, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, + 0x73, 0x20, 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0x70, 0x68, + 0x61, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, + 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x67, 0x65, 0x6e, + 0x6f, 0x6d, 0x65, 0x29, 0x0a, 0x0a, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x43, 0x46, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, - 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x63, 0x68, - 0x72, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x56, 0x43, 0x46, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x67, 0x65, 0x6e, + 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x0a, 0x23, 0x23, 0x23, 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, + 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20, 0x3a, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x2d, 0x20, + 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x0a, 0x67, + 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x46, 0x75, 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x20, 0x6f, 0x66, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x46, 0x75, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x28, 0x6e, 0x6f, 0x72, + 0x6d, 0x61, 0x6c, 0x29, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x53, 0x75, 0x70, 0x65, 0x72, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, + 0x73, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x70, 0x65, 0x72, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x23, 0x23, 0x23, + 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x44, 0x65, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x0a, 0x0a, + 0x23, 0x20, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x44, + 0x3a, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x73, 0x65, + 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x43, 0x46, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x20, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, + 0x65, 0x61, 0x64, 0x2e, 0x0a, 0x23, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, + 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x46, 0x69, 0x6c, + 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, + 0x23, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x56, 0x43, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x20, 0x53, 0x4e, 0x50, 0x73, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, + 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, + 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x28, 0x41, 0x46, 0x3e, + 0x30, 0x2e, 0x35, 0x29, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x29, + 0x0a, 0x23, 0x20, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, + 0x44, 0x20, 0x0a, 0x0a, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x53, 0x70, + 0x6c, 0x69, 0x63, 0x65, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x20, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x0a, + 0x73, 0x6a, 0x64, 0x62, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x68, 0x72, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x45, 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x70, 0x61, 0x74, + 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x65, 0x6e, 0x6f, + 0x6d, 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, + 0x74, 0x65, 0x73, 0x20, 0x28, 0x63, 0x68, 0x72, 0x20, 0x3c, 0x74, 0x61, + 0x62, 0x3e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x3c, 0x74, 0x61, + 0x62, 0x3e, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x3c, 0x74, 0x61, 0x62, 0x3e, + 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x29, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, + 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x74, + 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, + 0x6c, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x63, 0x61, 0x6e, + 0x20, 0x62, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, + 0x20, 0x77, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, + 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x6e, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, + 0x66, 0x69, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x72, 0x6f, - 0x6d, 0x6f, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x27, 0x63, 0x68, - 0x72, 0x27, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, - 0x20, 0x45, 0x4e, 0x53, 0x4d, 0x45, 0x42, 0x4c, 0x20, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x55, 0x43, 0x53, 0x43, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, - 0x65, 0x73, 0x29, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x45, 0x78, 0x6f, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, 0x6f, - 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x3a, 0x20, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x61, 0x73, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, + 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, + 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x63, 0x68, 0x72, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, + 0x6f, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x61, 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x27, 0x63, 0x68, 0x72, + 0x27, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, + 0x45, 0x4e, 0x53, 0x4d, 0x45, 0x42, 0x4c, 0x20, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x55, 0x43, 0x53, 0x43, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, + 0x73, 0x29, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x66, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x45, 0x78, 0x6f, 0x6e, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, 0x6f, 0x6e, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x69, 0x6e, 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x61, 0x73, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x0a, 0x0a, + 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x74, 0x61, 0x67, 0x45, 0x78, + 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x5f, 0x69, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x47, 0x54, 0x46, 0x20, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x49, + 0x44, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x22, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x69, + 0x64, 0x22, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x29, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x74, 0x61, 0x67, 0x45, - 0x78, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x47, 0x54, 0x46, 0x20, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, - 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, - 0x49, 0x44, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, - 0x22, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, - 0x69, 0x64, 0x22, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x47, 0x54, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x29, - 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, 0x74, 0x61, 0x67, - 0x45, 0x78, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x65, - 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x69, - 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x3a, 0x20, 0x47, 0x54, 0x46, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x67, 0x65, 0x6e, 0x65, - 0x20, 0x49, 0x44, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x20, 0x22, 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x54, 0x46, - 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x29, 0x0a, 0x0a, 0x73, 0x6a, 0x64, - 0x62, 0x47, 0x54, 0x46, 0x74, 0x61, 0x67, 0x45, 0x78, 0x6f, 0x6e, 0x50, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x4e, 0x61, 0x6d, + 0x78, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, - 0x3a, 0x20, 0x47, 0x54, 0x46, 0x20, 0x61, 0x74, 0x74, 0x72, 0x62, 0x75, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x69, 0x64, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x47, 0x54, 0x46, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, - 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, - 0x46, 0x74, 0x61, 0x67, 0x45, 0x78, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x65, - 0x6e, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, - 0x5f, 0x62, 0x69, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, - 0x47, 0x54, 0x46, 0x20, 0x61, 0x74, 0x74, 0x72, 0x62, 0x75, 0x74, 0x65, - 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x4f, 0x76, 0x65, 0x72, - 0x68, 0x61, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x64, 0x6f, 0x6e, 0x6f, 0x72, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, - 0x20, 0x6f, 0x6e, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x69, 0x64, - 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6a, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x64, 0x65, 0x61, - 0x6c, 0x6c, 0x79, 0x20, 0x3d, 0x20, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x5f, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x0a, - 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x3a, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x63, 0x6f, 0x72, - 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, - 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x6f, + 0x49, 0x44, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, + 0x22, 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x22, 0x20, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x54, 0x46, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x29, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, + 0x47, 0x54, 0x46, 0x74, 0x61, 0x67, 0x45, 0x78, 0x6f, 0x6e, 0x50, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, + 0x20, 0x47, 0x54, 0x46, 0x20, 0x61, 0x74, 0x74, 0x72, 0x62, 0x75, 0x74, + 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x6e, + 0x61, 0x6d, 0x65, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x47, 0x54, 0x46, + 0x74, 0x61, 0x67, 0x45, 0x78, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x47, 0x65, 0x6e, 0x65, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x65, 0x6e, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x5f, + 0x62, 0x69, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x47, + 0x54, 0x46, 0x20, 0x61, 0x74, 0x74, 0x72, 0x62, 0x75, 0x74, 0x65, 0x20, + 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x4f, 0x76, 0x65, 0x72, 0x68, + 0x61, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x64, 0x6f, 0x6e, 0x6f, 0x72, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x6f, 0x72, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x20, + 0x6f, 0x6e, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x69, 0x64, 0x65, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x64, 0x65, 0x61, 0x6c, + 0x6c, 0x79, 0x20, 0x3d, 0x20, 0x28, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x0a, 0x0a, + 0x73, 0x6a, 0x64, 0x62, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3a, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x20, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x73, 0x6a, 0x64, 0x62, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x53, 0x61, 0x76, @@ -482,32 +618,40 @@ unsigned char parametersDefault[] = { 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x79, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x65, 0x70, 0x0a, 0x09, 0x09, 0x09, - 0x09, 0x09, 0x42, 0x61, 0x73, 0x69, 0x63, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6a, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2f, 0x20, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x41, 0x6c, 0x6c, 0x20, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, - 0x67, 0x20, 0x62, 0x69, 0x67, 0x20, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, - 0x2c, 0x20, 0x53, 0x41, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x41, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, - 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x67, - 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x79, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x56, 0x61, 0x72, - 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x73, 0x0a, 0x76, 0x61, 0x72, 0x56, 0x43, 0x46, - 0x66, 0x69, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x65, 0x70, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, - 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x56, 0x43, 0x46, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x76, - 0x61, 0x72, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x49, 0x6e, 0x70, 0x75, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x61, 0x73, 0x69, 0x63, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x6d, 0x61, 0x6c, + 0x6c, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2f, + 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x69, 0x67, 0x20, + 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x2c, 0x20, 0x53, 0x41, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x53, 0x41, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x2d, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x0a, 0x23, + 0x23, 0x23, 0x20, 0x56, 0x61, 0x72, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x0a, + 0x76, 0x61, 0x72, 0x56, 0x43, 0x46, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x56, 0x43, 0x46, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x73, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65, + 0x20, 0x31, 0x30, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, + 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x30, + 0x2f, 0x31, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x42, 0x41, 0x4d, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, @@ -550,116 +694,237 @@ unsigned char parametersDefault[] = { 0x6f, 0x72, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x75, 0x73, 0x65, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6d, 0x74, 0x6f, 0x6f, - 0x6c, 0x73, 0x20, 0x76, 0x69, 0x65, 0x77, 0x0a, 0x0a, 0x72, 0x65, 0x61, - 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, + 0x6c, 0x73, 0x20, 0x76, 0x69, 0x65, 0x77, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x52, 0x65, 0x61, 0x64, 0x31, 0x20, 0x52, 0x65, 0x61, 0x64, 0x32, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, - 0x73, 0x29, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x74, 0x6f, - 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x31, 0x20, 0x28, 0x61, 0x6e, 0x64, - 0x2c, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2c, - 0x20, 0x20, 0x72, 0x65, 0x61, 0x64, 0x32, 0x29, 0x0a, 0x0a, 0x72, 0x65, - 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x65, 0x69, 0x66, 0x78, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2c, - 0x20, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x69, - 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x69, - 0x6e, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, - 0x73, 0x49, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x3a, 0x20, 0x6e, - 0x6f, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x0a, 0x0a, 0x72, 0x65, - 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x0a, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x41, + 0x4d, 0x61, 0x74, 0x74, 0x72, 0x4b, 0x65, 0x65, 0x70, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x54, 0x79, 0x70, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, + 0x53, 0x45, 0x2f, 0x50, 0x45, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x74, 0x6f, + 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x42, 0x41, 0x4d, 0x2c, + 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x3a, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, + 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x41, 0x4d, 0x74, 0x61, 0x67, + 0x73, 0x4b, 0x65, 0x65, 0x70, 0x20, 0x52, 0x47, 0x20, 0x50, 0x4c, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x61, 0x6c, 0x6c, + 0x20, 0x74, 0x61, 0x67, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, + 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, 0x6f, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x61, 0x67, 0x73, 0x0a, 0x0a, 0x72, 0x65, 0x61, 0x64, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x52, 0x65, 0x61, 0x64, 0x31, 0x20, 0x52, 0x65, 0x61, 0x64, 0x32, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, + 0x29, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x74, 0x6f, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x31, 0x20, 0x28, 0x61, 0x6e, 0x64, 0x2c, + 0x20, 0x69, 0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2c, 0x20, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x32, 0x29, 0x0a, 0x0a, 0x72, 0x65, 0x61, + 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, + 0x73, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x22, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x22, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, + 0x20, 0x54, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, + 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x33, 0x20, + 0x74, 0x61, 0x62, 0x2d, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3a, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, + 0x61, 0x69, 0x72, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x73, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x31, 0x5f, 0x66, + 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x24, 0x74, 0x61, + 0x62, 0x24, 0x20, 0x72, 0x65, 0x61, 0x64, 0x32, 0x5f, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x24, 0x74, 0x61, 0x62, 0x24, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, + 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x31, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x20, 0x24, 0x74, 0x61, 0x62, 0x24, 0x20, 0x2d, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x24, 0x74, 0x61, 0x62, 0x24, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x2e, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x62, 0x75, 0x74, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x61, 0x62, 0x73, 0x20, 0x61, 0x72, + 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x69, 0x6e, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x49, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x64, 0x6f, 0x65, 0x73, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x49, 0x44, 0x3a, 0x2c, 0x20, 0x69, 0x74, 0x20, + 0x63, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x49, 0x44, 0x20, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, + 0x44, 0x3a, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, + 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x49, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x49, 0x44, 0x3a, 0x2c, 0x20, + 0x69, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x73, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x24, 0x74, 0x61, 0x62, 0x24, + 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, + 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x20, 0x76, + 0x65, 0x72, 0x62, 0x61, 0x74, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x40, 0x52, 0x47, 0x20, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x0a, 0x0a, 0x72, + 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x20, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x20, 0x46, 0x41, 0x53, 0x54, 0x41, 0x20, 0x6f, - 0x72, 0x20, 0x46, 0x41, 0x53, 0x54, 0x51, 0x20, 0x74, 0x65, 0x78, 0x74, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x69, 0x74, - 0x20, 0x74, 0x6f, 0x20, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x3a, 0x20, 0x7a, 0x63, 0x61, 0x74, 0x20, 0x2d, 0x20, 0x74, 0x6f, - 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, - 0x2e, 0x67, 0x7a, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x62, - 0x7a, 0x63, 0x61, 0x74, 0x20, 0x2d, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, - 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x2e, 0x62, 0x7a, - 0x32, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x65, 0x74, 0x63, - 0x2e, 0x0a, 0x0a, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x61, 0x70, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x2c, 0x20, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, + 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, + 0x69, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, + 0x65, 0x73, 0x49, 0x6e, 0x0a, 0x0a, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, + 0x73, 0x29, 0x3a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, + 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x20, 0x46, 0x41, 0x53, 0x54, 0x41, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x41, + 0x53, 0x54, 0x51, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, + 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x6f, + 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x20, 0x7a, + 0x63, 0x61, 0x74, 0x20, 0x2d, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x63, + 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x2e, 0x67, 0x7a, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x62, 0x7a, 0x63, 0x61, 0x74, + 0x20, 0x2d, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, + 0x72, 0x65, 0x73, 0x73, 0x20, 0x2e, 0x62, 0x7a, 0x32, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x2e, 0x0a, 0x0a, 0x72, + 0x65, 0x61, 0x64, 0x4d, 0x61, 0x70, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, + 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, + 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2d, 0x31, 0x3a, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x61, 0x6c, 0x6c, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, 0x0a, 0x72, 0x65, 0x61, 0x64, + 0x4d, 0x61, 0x74, 0x65, 0x73, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x73, + 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x74, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x45, 0x71, 0x75, + 0x61, 0x6c, 0x2f, 0x4e, 0x6f, 0x74, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x20, + 0x2d, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x66, + 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2c, 0x73, 0x65, 0x71, 0x75, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x2c, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, + 0x6d, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x2f, 0x20, 0x6e, 0x6f, + 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x2e, 0x20, + 0x4e, 0x6f, 0x74, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x20, + 0x73, 0x61, 0x66, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, + 0x73, 0x69, 0x74, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, + 0x0a, 0x72, 0x65, 0x61, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x70, + 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x63, 0x68, + 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x28, 0x73, 0x29, 0x20, 0x73, + 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, + 0x65, 0x20, 0x74, 0x72, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x20, 0x69, 0x6e, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x28, 0x72, 0x65, 0x61, + 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, + 0x77, 0x61, 0x79, 0x73, 0x20, 0x74, 0x72, 0x69, 0x6d, 0x6d, 0x65, 0x64, + 0x29, 0x0a, 0x0a, 0x72, 0x65, 0x61, 0x64, 0x51, 0x75, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x73, 0x65, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x33, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, + 0x75, 0x62, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, + 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x53, 0x43, 0x49, 0x49, + 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, + 0x20, 0x50, 0x68, 0x72, 0x65, 0x64, 0x20, 0x71, 0x75, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x23, 0x23, + 0x23, 0x20, 0x52, 0x65, 0x61, 0x64, 0x20, 0x43, 0x6c, 0x69, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x70, 0x41, 0x64, 0x61, + 0x70, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x61, 0x6d, + 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x64, 0x61, + 0x70, 0x74, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, + 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, + 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x20, 0x62, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, + 0x20, 0x48, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x69, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, + 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x20, + 0x62, 0x79, 0x20, 0x2d, 0x2d, 0x63, 0x6c, 0x69, 0x70, 0x35, 0x70, 0x41, + 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x4d, 0x4d, 0x70, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, + 0x34, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x35, 0x70, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x33, 0x70, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, + 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x69, 0x6d, + 0x69, 0x6c, 0x61, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x43, 0x65, 0x6c, 0x6c, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x34, 0x2e, 0x20, 0x55, 0x74, 0x69, + 0x6c, 0x69, 0x7a, 0x65, 0x73, 0x20, 0x4f, 0x70, 0x61, 0x6c, 0x20, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x20, 0x62, 0x79, 0x20, 0x4d, 0x61, + 0x72, 0x74, 0x69, 0x6e, 0x20, 0xc5, 0xa0, 0x6f, 0xc5, 0xa1, 0x69, 0xc4, + 0x87, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4d, 0x61, + 0x72, 0x74, 0x69, 0x6e, 0x73, 0x6f, 0x73, 0x2f, 0x6f, 0x70, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x3a, 0x20, 0x6d, 0x61, 0x70, - 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, 0x0a, - 0x72, 0x65, 0x61, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x73, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x73, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x74, 0x45, 0x71, 0x75, 0x61, 0x6c, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, - 0x20, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x2f, 0x4e, 0x6f, 0x74, 0x45, 0x71, - 0x75, 0x61, 0x6c, 0x20, 0x2d, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2c, 0x73, - 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2c, 0x71, 0x75, 0x61, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, - 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, - 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x20, - 0x2f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, - 0x6d, 0x65, 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x45, 0x71, 0x75, 0x61, 0x6c, - 0x20, 0x69, 0x73, 0x20, 0x73, 0x61, 0x66, 0x65, 0x20, 0x69, 0x6e, 0x20, - 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x69, 0x74, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x72, 0x65, 0x61, 0x64, 0x4e, 0x61, 0x6d, - 0x65, 0x53, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, - 0x3a, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x28, - 0x73, 0x29, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6e, - 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x72, 0x69, 0x6d, 0x6d, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, - 0x28, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x69, - 0x73, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x74, 0x72, 0x69, - 0x6d, 0x6d, 0x65, 0x64, 0x29, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x70, 0x33, - 0x70, 0x4e, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x73, 0x29, - 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x73, 0x29, 0x20, - 0x6f, 0x66, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x63, 0x6c, 0x69, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x33, 0x70, - 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, - 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, - 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, - 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, - 0x74, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x63, - 0x6c, 0x69, 0x70, 0x35, 0x70, 0x4e, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, + 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, + 0x6c, 0x6c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x69, + 0x70, 0x2a, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x64, 0x69, 0x73, 0x72, 0x65, 0x67, + 0x61, 0x72, 0x64, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x63, + 0x6c, 0x69, 0x70, 0x33, 0x70, 0x4e, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, 0x73, 0x29, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x35, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, + 0x6d, 0x20, 0x33, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, @@ -679,38 +944,98 @@ unsigned char parametersDefault[] = { 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, - 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x63, 0x6c, 0x69, - 0x70, 0x33, 0x70, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x4d, 0x4d, - 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, - 0x62, 0x6c, 0x65, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, - 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x33, 0x70, 0x20, 0x61, 0x64, 0x70, 0x61, + 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x70, 0x6f, 0x6c, 0x79, 0x41, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x70, 0x6f, + 0x6c, 0x79, 0x41, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x74, + 0x6f, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x70, 0x33, 0x70, 0x41, 0x64, 0x61, + 0x70, 0x74, 0x65, 0x72, 0x4d, 0x4d, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x31, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x28, 0x73, 0x29, + 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x33, + 0x70, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x63, 0x6c, + 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, + 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x20, 0x49, + 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x74, + 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x73, + 0x75, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, + 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, + 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x70, 0x33, + 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, + 0x72, 0x4e, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x30, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x28, 0x73, 0x29, 0x3a, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, + 0x61, 0x73, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, + 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x33, 0x70, 0x20, 0x6f, 0x66, 0x20, + 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x61, 0x66, + 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, - 0x74, 0x65, 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, - 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, - 0x62, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, - 0x0a, 0x63, 0x6c, 0x69, 0x70, 0x33, 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, - 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x4e, 0x62, 0x61, 0x73, 0x65, - 0x73, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x33, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, - 0x61, 0x74, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x63, 0x6c, - 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6f, - 0x6e, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, - 0x67, 0x69, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, - 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, - 0x73, 0x2e, 0x0a, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4c, 0x69, 0x6d, + 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x2c, + 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, + 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x63, 0x6c, + 0x69, 0x70, 0x35, 0x70, 0x4e, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, + 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x28, + 0x73, 0x29, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, + 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, + 0x20, 0x35, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, + 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6f, 0x6e, 0x65, + 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, + 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, + 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, + 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20, 0x3a, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x2d, 0x20, + 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x20, 0x20, + 0x20, 0x0a, 0x63, 0x6c, 0x69, 0x70, 0x35, 0x70, 0x41, 0x64, 0x61, 0x70, + 0x74, 0x65, 0x72, 0x53, 0x65, 0x71, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x61, + 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x69, 0x70, + 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x35, 0x70, 0x20, 0x6f, 0x66, 0x20, + 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x73, + 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x70, + 0x35, 0x70, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x4d, 0x4d, 0x70, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x75, 0x62, + 0x6c, 0x65, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x70, + 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, + 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x35, 0x70, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, + 0x65, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, + 0x65, 0x2c, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, + 0x20, 0x62, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x0a, 0x0a, 0x63, + 0x6c, 0x69, 0x70, 0x35, 0x70, 0x41, 0x66, 0x74, 0x65, 0x72, 0x41, 0x64, + 0x61, 0x70, 0x74, 0x65, 0x72, 0x4e, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, + 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, + 0x6f, 0x66, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, + 0x63, 0x6c, 0x69, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x35, 0x70, + 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, + 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x2e, 0x0a, 0x23, 0x23, 0x23, 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, + 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x0a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x52, 0x41, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, @@ -723,1304 +1048,1535 @@ unsigned char parametersDefault[] = { 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x49, 0x4f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x35, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x61, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x73, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x28, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x2f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, - 0x70, 0x65, 0x72, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x0a, 0x0a, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x4f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x6f, - 0x6e, 0x65, 0x52, 0x65, 0x61, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x73, - 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, - 0x41, 0x4d, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x28, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x6e, - 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x52, 0x65, 0x63, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x20, 0x3e, 0x28, 0x32, 0x2a, 0x28, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x4d, 0x61, 0x74, 0x65, 0x31, 0x2b, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x4d, 0x61, 0x74, 0x65, 0x32, 0x2b, 0x31, 0x30, 0x30, 0x29, - 0x2a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x0a, 0x0a, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x4f, 0x75, 0x74, 0x53, 0x4a, 0x6f, 0x6e, - 0x65, 0x52, 0x65, 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x35, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, + 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, + 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x28, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2f, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x70, 0x65, 0x72, 0x20, + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x4f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x6f, 0x6e, 0x65, 0x52, 0x65, + 0x61, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, + 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x72, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x28, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x2e, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x20, 0x3e, + 0x28, 0x32, 0x2a, 0x28, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, + 0x74, 0x65, 0x31, 0x2b, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, + 0x74, 0x65, 0x32, 0x2b, 0x31, 0x30, 0x30, 0x29, 0x2a, 0x6f, 0x75, 0x74, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, + 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x4f, 0x75, 0x74, 0x53, 0x4a, 0x6f, 0x6e, 0x65, 0x52, 0x65, 0x61, + 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, + 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, + 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, + 0x6f, 0x66, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, 0x65, 0x61, + 0x64, 0x20, 0x28, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, + 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x29, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, + 0x69, 0x74, 0x4f, 0x75, 0x74, 0x53, 0x4a, 0x63, 0x6f, 0x6c, 0x6c, 0x61, + 0x70, 0x73, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x65, - 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x28, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x29, 0x0a, - 0x0a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x4f, 0x75, 0x74, 0x53, 0x4a, 0x63, - 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, - 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, - 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x42, 0x41, 0x4d, 0x73, 0x6f, 0x72, 0x74, 0x52, 0x41, 0x4d, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x3d, 0x30, - 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x52, 0x41, 0x4d, 0x20, - 0x28, 0x62, 0x79, 0x74, 0x65, 0x73, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x42, 0x41, 0x4d, 0x2e, - 0x20, 0x49, 0x66, 0x20, 0x3d, 0x30, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, - 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, - 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2e, - 0x20, 0x30, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x63, 0x61, 0x6e, - 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, - 0x6f, 0x6d, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x20, 0x4e, 0x6f, 0x53, 0x68, - 0x61, 0x72, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, - 0x74, 0x53, 0x6a, 0x64, 0x62, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4e, - 0x73, 0x6a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, - 0x75, 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, - 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, - 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, - 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, - 0x79, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x61, 0x67, 0x65, 0x2c, 0x20, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, - 0x6f, 0x73, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, - 0x73, 0x74, 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, 0x72, 0x75, - 0x6e, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x4e, 0x72, 0x65, 0x61, - 0x64, 0x73, 0x53, 0x6f, 0x66, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x73, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x3a, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, - 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2f, 0x0a, + 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, + 0x70, 0x73, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x41, 0x4d, + 0x73, 0x6f, 0x72, 0x74, 0x52, 0x41, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x61, + 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x52, 0x41, 0x4d, 0x20, 0x28, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x72, 0x74, + 0x69, 0x6e, 0x67, 0x20, 0x42, 0x41, 0x4d, 0x2e, 0x20, 0x49, 0x66, 0x20, + 0x3d, 0x30, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2e, 0x20, 0x30, 0x20, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, + 0x79, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x4c, + 0x6f, 0x61, 0x64, 0x20, 0x4e, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, + 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x0a, 0x0a, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x53, 0x6a, 0x64, + 0x62, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4e, 0x73, 0x6a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x3d, + 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6a, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, + 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x6f, + 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x79, 0x20, 0x61, 0x74, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x20, 0x73, 0x74, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, + 0x73, 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, 0x73, 0x74, 0x20, 0x73, + 0x74, 0x65, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x32, + 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, 0x72, 0x75, 0x6e, 0x0a, 0x0a, 0x6c, + 0x69, 0x6d, 0x69, 0x74, 0x4e, 0x72, 0x65, 0x61, 0x64, 0x73, 0x53, 0x6f, + 0x66, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, + 0x3a, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, + 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3a, + 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x0a, 0x6f, 0x75, 0x74, + 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x6e, 0x61, 0x6d, + 0x65, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x28, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x75, 0x6c, 0x6c, + 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x20, 0x70, 0x61, 0x74, 0x68, 0x29, 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, + 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, + 0x6e, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2e, + 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x54, 0x6d, 0x70, 0x44, 0x69, 0x72, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, - 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x20, 0x28, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, - 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x29, 0x2e, 0x20, - 0x43, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, - 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, - 0x69, 0x6e, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x54, 0x6d, 0x70, - 0x44, 0x69, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, + 0x64, 0x20, 0x61, 0x73, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, + 0x72, 0x79, 0x20, 0x62, 0x79, 0x20, 0x53, 0x54, 0x41, 0x52, 0x2e, 0x20, + 0x41, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x21, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x20, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x77, 0x69, 0x6c, + 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, + 0x20, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x74, + 0x6d, 0x70, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x54, 0x6d, 0x70, 0x4b, 0x65, + 0x65, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, - 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, - 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x74, 0x65, 0x6d, - 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x20, 0x62, 0x79, 0x20, 0x53, 0x54, - 0x41, 0x52, 0x2e, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x77, - 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x64, 0x21, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, - 0x6d, 0x70, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, - 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x53, - 0x54, 0x41, 0x52, 0x74, 0x6d, 0x70, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x54, - 0x6d, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x77, 0x68, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x65, 0x65, 0x70, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x70, 0x6f, 0x72, - 0x61, 0x72, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, 0x20, 0x72, 0x75, 0x6e, - 0x73, 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, - 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x74, 0x65, 0x6d, 0x70, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, + 0x53, 0x54, 0x41, 0x52, 0x20, 0x72, 0x75, 0x6e, 0x73, 0x20, 0x69, 0x73, + 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, - 0x6e, 0x65, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, - 0x61, 0x72, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, + 0x6c, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x2e, 0x2e, - 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x2e, 0x2e, 0x20, 0x6b, 0x65, 0x65, + 0x70, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4c, 0x6f, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, - 0x65, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, - 0x6f, 0x20, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x20, 0x28, 0x73, 0x74, - 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x29, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x6f, 0x67, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x74, + 0x64, 0x6f, 0x75, 0x74, 0x20, 0x28, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, + 0x72, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x6f, 0x67, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x4c, 0x6f, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, - 0x6f, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0a, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, - 0x20, 0x53, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, - 0x28, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, - 0x6c, 0x6c, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x73, 0x61, 0x6d, 0x20, 0x66, 0x69, - 0x6c, 0x65, 0x29, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, - 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20, - 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f, 0x67, 0x2e, 0x73, 0x74, 0x64, - 0x2e, 0x6f, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x28, 0x77, 0x68, 0x69, + 0x63, 0x68, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x6c, 0x79, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x74, + 0x6f, 0x20, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x6f, 0x75, + 0x74, 0x2e, 0x73, 0x61, 0x6d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x29, 0x2c, + 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61, 0x6e, + 0x64, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20, 0x69, 0x6e, 0x74, 0x6f, + 0x20, 0x4c, 0x6f, 0x67, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x6f, 0x75, 0x74, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x41, 0x4d, + 0x5f, 0x55, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, + 0x6e, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x2c, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x20, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x2d, 0x2d, 0x6f, + 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x42, 0x41, + 0x4d, 0x20, 0x55, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x41, 0x4d, 0x5f, 0x53, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, 0x6f, 0x6f, 0x72, 0x64, + 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, + 0x42, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2c, 0x20, + 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, + 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, + 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x42, 0x41, 0x4d, 0x20, + 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, 0x6f, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x42, 0x41, 0x4d, 0x5f, 0x51, 0x75, 0x61, 0x6e, 0x74, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, + 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2c, + 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x52, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x2d, 0x2d, 0x71, 0x75, + 0x61, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x53, 0x41, 0x4d, + 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x61, 0x64, 0x73, 0x55, 0x6e, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, + 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x3a, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, + 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x6d, + 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, + 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x61, 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x64, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x29, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, + 0x20, 0x69, 0x6e, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x42, 0x41, 0x4d, 0x5f, 0x55, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, - 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x55, 0x6e, 0x73, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, - 0x41, 0x4d, 0x5f, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, - 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x20, 0x69, 0x6e, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x2d, - 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, - 0x42, 0x41, 0x4d, 0x20, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, - 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x41, 0x4d, 0x5f, 0x51, - 0x75, 0x61, 0x6e, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, - 0x65, 0x20, 0x69, 0x6e, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, - 0x2d, 0x2d, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x20, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, - 0x65, 0x53, 0x41, 0x4d, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x61, - 0x64, 0x73, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x20, 0x6f, 0x66, 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, - 0x6c, 0x79, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x28, 0x69, - 0x2e, 0x65, 0x2e, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, - 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, - 0x20, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x29, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x65, 0x70, 0x61, - 0x72, 0x61, 0x74, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x29, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x46, 0x61, 0x73, 0x74, 0x78, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x65, + 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x66, 0x61, 0x73, 0x74, 0x61, + 0x2f, 0x66, 0x61, 0x73, 0x74, 0x71, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x2c, 0x20, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x2e, 0x6f, + 0x75, 0x74, 0x2e, 0x6d, 0x61, 0x74, 0x65, 0x31, 0x2f, 0x32, 0x0a, 0x0a, + 0x6f, 0x75, 0x74, 0x51, 0x53, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, + 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x64, 0x64, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, + 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x49, 0x6c, 0x6c, 0x75, 0x6d, 0x69, 0x6e, + 0x61, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2c, + 0x20, 0x75, 0x73, 0x65, 0x20, 0x2d, 0x33, 0x31, 0x29, 0x0a, 0x0a, 0x6f, + 0x75, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, 0x65, + 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x6c, 0x64, 0x5f, 0x32, + 0x2e, 0x34, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, - 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x4f, 0x6c, 0x64, 0x5f, 0x32, 0x2e, 0x34, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x71, 0x75, 0x61, 0x73, 0x69, 0x2d, 0x72, 0x61, + 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x75, + 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x32, + 0x2e, 0x35, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, + 0x20, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, + 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x65, + 0x72, 0x2e, 0x20, 0x52, 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, + 0x73, 0x20, 0x28, 0x70, 0x61, 0x69, 0x72, 0x73, 0x29, 0x20, 0x61, 0x72, + 0x65, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x61, 0x64, 0x6a, + 0x61, 0x63, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x73, + 0x74, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d, + 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x6e, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, + 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x23, + 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3a, 0x20, 0x53, + 0x41, 0x4d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x42, 0x41, 0x4d, 0x0a, 0x6f, + 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x41, 0x4d, 0x2f, + 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x73, 0x74, 0x20, 0x77, + 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x42, 0x41, 0x4d, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x6f, 0x75, 0x74, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, + 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x53, 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x46, 0x61, 0x73, 0x74, 0x78, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x69, - 0x6e, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x66, - 0x61, 0x73, 0x74, 0x61, 0x2f, 0x66, 0x61, 0x73, 0x74, 0x71, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, - 0x65, 0x64, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x6d, 0x61, 0x74, 0x65, 0x31, - 0x2f, 0x32, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x51, 0x53, 0x63, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x64, - 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x28, - 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x49, 0x6c, 0x6c, - 0x75, 0x6d, 0x69, 0x6e, 0x61, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x6e, - 0x67, 0x65, 0x72, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x20, 0x2d, 0x33, 0x31, - 0x29, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, - 0x61, 0x70, 0x70, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, - 0x6c, 0x64, 0x5f, 0x32, 0x2e, 0x34, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x6c, 0x64, 0x5f, - 0x32, 0x2e, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x71, 0x75, 0x61, 0x73, - 0x69, 0x2d, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, - 0x72, 0x65, 0x20, 0x32, 0x2e, 0x35, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, - 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e, 0x20, 0x52, 0x65, 0x61, 0x64, 0x20, - 0x6d, 0x61, 0x74, 0x65, 0x73, 0x20, 0x28, 0x70, 0x61, 0x69, 0x72, 0x73, - 0x29, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, - 0x20, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, - 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x73, 0x74, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x67, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, - 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, - 0x75, 0x72, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x73, - 0x2e, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x3a, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x42, - 0x41, 0x4d, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, 0x64, 0x2c, 0x20, 0x33, 0x72, 0x64, + 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, + 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x61, + 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x41, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x73, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x53, 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, 0x6f, 0x6f, 0x72, 0x64, + 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x77, + 0x68, 0x69, 0x63, 0x68, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, + 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x62, 0x79, + 0x20, 0x2d, 0x2d, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x41, 0x4d, 0x73, + 0x6f, 0x72, 0x74, 0x52, 0x41, 0x4d, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, + 0x53, 0x41, 0x4d, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x75, 0x6c, 0x6c, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6d, 0x6f, + 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, - 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x42, 0x41, 0x4d, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x73, 0x6f, 0x72, - 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x75, 0x6c, 0x6c, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x53, 0x41, + 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x41, 0x4d, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x6f, 0x75, 0x74, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x51, 0x53, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x62, + 0x75, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x71, + 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x73, 0x74, 0x72, + 0x61, 0x6e, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, + 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x3a, 0x20, 0x43, 0x75, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x6b, + 0x73, 0x2d, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, + 0x64, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, - 0x65, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x53, 0x41, 0x4d, - 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, + 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, 0x64, 0x2c, - 0x20, 0x33, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, + 0x4d, 0x6f, 0x74, 0x69, 0x66, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, + 0x72, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, + 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, + 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2e, 0x20, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6e, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, + 0x72, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, + 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x73, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, + 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, + 0x4d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, + 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, + 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x20, 0x53, 0x41, 0x4d, 0x20, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2c, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x53, 0x41, 0x4d, 0x2e, 0x20, 0x54, 0x61, 0x67, 0x73, 0x20, 0x63, 0x61, + 0x6e, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x20, + 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x2a, + 0x2a, 0x50, 0x72, 0x65, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x55, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x75, 0x6e, - 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, + 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, + 0x64, 0x61, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x4e, 0x48, 0x20, 0x48, 0x49, 0x20, 0x41, 0x53, 0x20, 0x6e, 0x4d, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x4e, 0x48, 0x20, 0x48, 0x49, 0x20, 0x41, 0x53, 0x20, 0x6e, 0x4d, 0x20, + 0x4e, 0x4d, 0x20, 0x4d, 0x44, 0x20, 0x6a, 0x4d, 0x20, 0x6a, 0x49, 0x20, + 0x4d, 0x43, 0x20, 0x63, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, - 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, - 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x2e, 0x20, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, - 0x65, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x6d, 0x65, 0x6d, 0x6f, - 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x63, 0x61, 0x6e, - 0x20, 0x62, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x2d, 0x2d, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x42, 0x41, 0x4d, 0x73, 0x6f, 0x72, 0x74, 0x52, 0x41, 0x4d, 0x2e, 0x0a, - 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x6d, 0x6f, 0x64, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x75, 0x6c, - 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x3a, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x41, - 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x46, 0x75, 0x6c, 0x6c, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, - 0x6c, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x2a, + 0x2a, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x48, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x6f, + 0x63, 0x69, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, + 0x20, 0x6d, 0x61, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x3a, 0x20, 0x3d, 0x31, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x3e, 0x31, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, + 0x70, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, + 0x72, 0x64, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x74, 0x61, 0x67, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x49, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x2c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, + 0x74, 0x72, 0x49, 0x48, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x28, 0x3d, + 0x31, 0x20, 0x62, 0x79, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x29, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, + 0x53, 0x41, 0x4d, 0x20, 0x74, 0x61, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x2b, 0x31, 0x2f, 0x2d, + 0x31, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x2f, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x65, 0x63, 0x68, 0x65, + 0x73, 0x2c, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x2a, 0x20, 0x70, 0x65, + 0x6e, 0x61, 0x6c, 0x74, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x69, 0x6e, 0x64, 0x65, 0x6c, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, + 0x61, 0x70, 0x73, 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x50, 0x45, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x77, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x53, 0x74, + 0x61, 0x64, 0x6e, 0x61, 0x72, 0x64, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x74, + 0x61, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x6e, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, + 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, + 0x2e, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x50, 0x45, 0x20, 0x72, 0x65, 0x61, + 0x64, 0x73, 0x2c, 0x20, 0x73, 0x75, 0x6d, 0x20, 0x6f, 0x76, 0x65, 0x72, + 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x4d, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x65, 0x64, 0x69, 0x74, 0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x28, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x64, 0x20, 0x2b, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, + 0x74, 0x65, 0x64, 0x20, 0x2b, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x29, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, + 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x74, 0x61, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4d, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x69, + 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x20, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, + 0x20, 0x28, 0x73, 0x65, 0x65, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, + 0x72, 0x64, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0x2e, 0x20, + 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x74, 0x61, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x6a, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, + 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x61, 0x6c, 0x6c, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x4e, 0x20, 0x69, 0x6e, + 0x20, 0x43, 0x49, 0x47, 0x41, 0x52, 0x29, 0x3a, 0x20, 0x30, 0x3a, 0x20, + 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, + 0x6c, 0x3b, 0x20, 0x31, 0x3a, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x47, 0x2c, + 0x20, 0x32, 0x3a, 0x20, 0x43, 0x54, 0x2f, 0x41, 0x43, 0x2c, 0x20, 0x33, + 0x3a, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, 0x2c, 0x20, 0x34, 0x3a, 0x20, + 0x43, 0x54, 0x2f, 0x47, 0x43, 0x2c, 0x20, 0x35, 0x3a, 0x20, 0x41, 0x54, + 0x2f, 0x41, 0x43, 0x2c, 0x20, 0x36, 0x3a, 0x20, 0x47, 0x54, 0x2f, 0x41, + 0x54, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, + 0x73, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x6a, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x32, 0x30, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, + 0x20, 0x69, 0x74, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x20, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x6a, 0x49, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x69, + 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, + 0x6c, 0x6c, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x28, 0x31, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x64, 0x29, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x53, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, + 0x72, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, + 0x41, 0x4d, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, + 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x27, 0x73, 0x20, 0x43, 0x49, + 0x47, 0x41, 0x52, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x20, + 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x74, 0x61, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x63, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x20, + 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, + 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x68, 0x69, 0x6d, 0x65, + 0x72, 0x69, 0x63, 0x20, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x2d, 0x2d, 0x63, 0x68, 0x69, + 0x6d, 0x4f, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x20, 0x57, 0x69, 0x74, + 0x68, 0x69, 0x6e, 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, + 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, + 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x3a, 0x20, 0x35, + 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x33, 0x27, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x2a, 0x2a, 0x56, 0x61, 0x72, 0x69, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x76, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, + 0x6e, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x47, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, + 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, + 0x6e, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, + 0x6c, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x76, 0x57, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x31, 0x20, 0x2d, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x70, 0x61, + 0x73, 0x73, 0x65, 0x73, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x32, 0x2c, 0x33, + 0x2c, 0x34, 0x2c, 0x35, 0x2c, 0x36, 0x2c, 0x37, 0x20, 0x2d, 0x20, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x65, + 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x57, + 0x41, 0x53, 0x50, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, + 0x2d, 0x2d, 0x77, 0x61, 0x73, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x74, 0x61, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x51, - 0x53, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x53, - 0x41, 0x4d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, - 0x75, 0x74, 0x20, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, - 0x63, 0x6f, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, - 0x4d, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x2a, 0x2a, + 0x53, 0x54, 0x41, 0x52, 0x73, 0x6f, 0x6c, 0x6f, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, - 0x43, 0x75, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x2d, 0x6c, 0x69, - 0x6b, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x52, 0x20, 0x43, 0x59, 0x20, + 0x55, 0x52, 0x20, 0x55, 0x59, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, + 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x55, 0x4d, 0x49, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x6f, 0x6c, 0x6f, 0x2a, 0x20, 0x64, 0x65, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x74, - 0x20, 0x75, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x4d, 0x6f, 0x74, 0x69, - 0x66, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, - 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, - 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2e, 0x20, 0x52, 0x65, 0x61, 0x64, - 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6e, - 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, - 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, - 0x69, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x73, - 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, - 0x64, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, - 0x41, 0x4d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, - 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, - 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x20, 0x53, 0x41, 0x4d, - 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2c, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, - 0x72, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x20, 0x53, 0x41, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4e, 0x48, 0x20, 0x48, 0x49, 0x20, 0x41, 0x53, 0x20, 0x6e, 0x4d, - 0x20, 0x4e, 0x4d, 0x20, 0x4d, 0x44, 0x20, 0x6a, 0x4d, 0x20, 0x6a, 0x49, - 0x20, 0x58, 0x53, 0x20, 0x4d, 0x43, 0x20, 0x63, 0x68, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x79, - 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x4e, 0x48, 0x20, - 0x48, 0x49, 0x20, 0x41, 0x53, 0x20, 0x6e, 0x4d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x4e, 0x48, 0x20, - 0x48, 0x49, 0x20, 0x41, 0x53, 0x20, 0x6e, 0x4d, 0x20, 0x4e, 0x4d, 0x20, - 0x4d, 0x44, 0x20, 0x6a, 0x4d, 0x20, 0x6a, 0x49, 0x20, 0x4d, 0x43, 0x20, - 0x63, 0x68, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x20, 0x61, - 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x76, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, - 0x63, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x74, 0x65, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x72, 0x69, - 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x70, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, - 0x57, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x30, 0x2f, 0x31, 0x20, 0x2d, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, - 0x6e, 0x6f, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x2f, 0x20, 0x70, - 0x61, 0x73, 0x73, 0x65, 0x73, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x2d, 0x2d, 0x77, 0x61, 0x73, - 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x20, - 0x53, 0x41, 0x4d, 0x74, 0x61, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x43, 0x52, 0x20, 0x43, 0x59, 0x20, 0x55, 0x52, 0x20, - 0x55, 0x59, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x71, 0x75, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x20, - 0x6f, 0x66, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, - 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x55, 0x4d, 0x49, - 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, - 0x6c, 0x6f, 0x2a, 0x20, 0x64, 0x65, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x2f, 0x75, 0x6e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x65, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x42, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x63, 0x6f, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x52, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x72, - 0x69, 0x61, 0x6e, 0x74, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, - 0x61, 0x74, 0x74, 0x72, 0x49, 0x48, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, - 0x3d, 0x30, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x48, 0x20, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x2e, 0x20, 0x30, 0x20, - 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, - 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x73, - 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x63, - 0x68, 0x20, 0x61, 0x73, 0x20, 0x43, 0x75, 0x66, 0x66, 0x6c, 0x69, 0x6e, - 0x6b, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x54, 0x69, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, - 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x58, 0x20, 0x47, 0x4e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, + 0x65, 0x6e, 0x65, 0x20, 0x49, 0x44, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, + 0x65, 0x6e, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x67, 0x65, 0x6e, 0x65, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x6e, 0x6d, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x69, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x67, 0x78, 0x20, 0x67, 0x6e, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x65, + 0x20, 0x49, 0x44, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x65, 0x6e, + 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x43, 0x42, 0x20, 0x55, 0x42, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2d, + 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x63, 0x65, + 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x55, 0x4d, 0x49, 0x73, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x73, 0x6f, 0x6c, 0x6f, 0x2a, 0x20, 0x64, 0x65, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x52, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x2d, 0x2d, 0x6f, 0x75, + 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x42, 0x41, 0x4d, + 0x20, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, 0x6f, 0x6f, + 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x73, 0x73, + 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x43, + 0x42, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x55, 0x4d, 0x49, 0x2e, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x53, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x72, 0x65, 0x20, 0x62, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x28, 0x43, 0x42, 0x2c, 0x55, 0x4d, + 0x49, 0x2c, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x57, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, - 0x65, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, - 0x20, 0x53, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x69, - 0x2e, 0x65, 0x2e, 0x20, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, - 0x6f, 0x75, 0x74, 0x2e, 0x73, 0x61, 0x6d, 0x29, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, - 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, - 0x65, 0x65, 0x70, 0x50, 0x61, 0x69, 0x72, 0x73, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x75, 0x6e, 0x6d, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x69, - 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x6e, - 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x2c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x20, 0x61, - 0x64, 0x6a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x69, - 0x74, 0x73, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6d, 0x61, - 0x74, 0x65, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x61, 0x66, 0x66, - 0x65, 0x63, 0x74, 0x73, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, - 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, - 0x61, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, - 0x66, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x51, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x72, 0x65, 0x20, 0x62, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x50, 0x61, 0x69, 0x72, 0x65, 0x64, 0x3a, 0x20, 0x6f, 0x6e, 0x65, - 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, - 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2a, 0x2a, 0x2a, 0x55, 0x6e, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x2f, 0x75, 0x6e, 0x64, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x69, 0x72, - 0x65, 0x64, 0x4b, 0x65, 0x65, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4f, - 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x61, - 0x74, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, - 0x6c, 0x6c, 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6b, - 0x65, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, - 0x20, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x20, 0x46, 0x41, 0x53, 0x54, 0x51, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, - 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x46, 0x6c, 0x61, 0x67, 0x09, - 0x09, 0x4f, 0x6e, 0x65, 0x42, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x72, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x68, 0x61, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x68, 0x61, 0x70, 0x6c, + 0x6f, 0x74, 0x79, 0x70, 0x65, 0x20, 0x28, 0x31, 0x2f, 0x32, 0x29, 0x20, + 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x70, 0x6c, + 0x6f, 0x69, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x2e, 0x20, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x67, 0x65, 0x6e, + 0x6f, 0x6d, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, + 0x6f, 0x6d, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, + 0x54, 0x79, 0x70, 0x65, 0x20, 0x44, 0x69, 0x70, 0x6c, 0x6f, 0x69, 0x64, + 0x20, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x42, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x6f, 0x6d, + 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, + 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x76, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6f, + 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x2e, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, 0x74, 0x72, 0x49, + 0x48, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x49, 0x48, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x2e, 0x20, 0x30, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, + 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x62, + 0x79, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, + 0x43, 0x75, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x20, 0x6f, 0x72, + 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x65, 0x2e, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x75, 0x6e, 0x6d, 0x61, 0x70, + 0x70, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x3a, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x6c, 0x69, 0x67, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, - 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x70, 0x72, - 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2d, 0x20, 0x61, 0x6c, 0x6c, 0x20, - 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, - 0x62, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x30, 0x78, 0x31, 0x30, 0x30, 0x20, 0x62, 0x69, 0x74, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x4c, 0x41, 0x47, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x28, 0x73, 0x29, 0x3a, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x6f, 0x66, 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x6e, 0x65, - 0x42, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x73, - 0x63, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x41, 0x6c, 0x6c, 0x42, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x72, 0x65, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6d, - 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x72, - 0x65, 0x61, 0x64, 0x49, 0x44, 0x09, 0x09, 0x09, 0x53, 0x74, 0x61, 0x6e, - 0x64, 0x61, 0x72, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x49, 0x44, - 0x20, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, - 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x69, - 0x72, 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x28, 0x75, 0x6e, - 0x74, 0x69, 0x6c, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x29, 0x20, 0x66, - 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x41, 0x53, 0x54, - 0x78, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x49, 0x44, 0x20, 0x6c, 0x69, - 0x6e, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, - 0x20, 0x2f, 0x31, 0x2c, 0x2f, 0x32, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x20, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x41, 0x53, 0x54, - 0x78, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, - 0x41, 0x4d, 0x6d, 0x61, 0x70, 0x71, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x35, 0x35, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x30, 0x20, 0x74, - 0x6f, 0x20, 0x32, 0x35, 0x35, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, - 0x41, 0x50, 0x51, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x6d, 0x61, 0x70, - 0x70, 0x65, 0x72, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, - 0x66, 0x6c, 0x61, 0x67, 0x4f, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x3a, 0x20, 0x30, 0x20, 0x74, 0x6f, 0x20, 0x36, 0x35, 0x35, - 0x33, 0x35, 0x3a, 0x20, 0x73, 0x61, 0x6d, 0x20, 0x46, 0x4c, 0x41, 0x47, - 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x62, 0x69, 0x74, - 0x77, 0x69, 0x73, 0x65, 0x20, 0x4f, 0x52, 0x27, 0x64, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2c, 0x20, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x46, 0x4c, 0x41, 0x47, - 0x3d, 0x46, 0x4c, 0x41, 0x47, 0x20, 0x7c, 0x20, 0x6f, 0x75, 0x74, 0x53, - 0x41, 0x4d, 0x66, 0x6c, 0x61, 0x67, 0x4f, 0x52, 0x2e, 0x20, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, - 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, - 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, - 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x53, - 0x54, 0x41, 0x52, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, - 0x65, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, 0x61, - 0x67, 0x41, 0x4e, 0x44, 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, - 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x74, - 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x62, 0x69, - 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, - 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x77, 0x69, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, - 0x41, 0x4d, 0x66, 0x6c, 0x61, 0x67, 0x41, 0x4e, 0x44, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x36, 0x35, 0x35, 0x33, - 0x35, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x30, - 0x20, 0x74, 0x6f, 0x20, 0x36, 0x35, 0x35, 0x33, 0x35, 0x3a, 0x20, 0x73, - 0x61, 0x6d, 0x20, 0x46, 0x4c, 0x41, 0x47, 0x20, 0x77, 0x69, 0x6c, 0x6c, - 0x20, 0x62, 0x65, 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, 0x20, - 0x41, 0x4e, 0x44, 0x27, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, - 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, - 0x2e, 0x65, 0x2e, 0x20, 0x46, 0x4c, 0x41, 0x47, 0x3d, 0x46, 0x4c, 0x41, - 0x47, 0x20, 0x26, 0x20, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, - 0x61, 0x67, 0x4f, 0x52, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, - 0x73, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x61, 0x67, - 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, - 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x53, 0x54, 0x41, 0x52, 0x2c, - 0x20, 0x62, 0x75, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, - 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, 0x61, 0x67, 0x4f, 0x52, - 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x73, 0x65, 0x74, 0x20, 0x73, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x73, 0x74, 0x20, + 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, + 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x69, 0x74, 0x68, 0x69, + 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x41, 0x4d, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x41, + 0x6c, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x73, + 0x61, 0x6d, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x32, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, 0x65, 0x65, 0x70, 0x50, 0x61, + 0x69, 0x72, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x20, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, + 0x6d, 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, + 0x68, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2c, + 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, + 0x65, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x6e, 0x73, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6b, 0x65, + 0x65, 0x70, 0x20, 0x69, 0x74, 0x20, 0x61, 0x64, 0x6a, 0x61, 0x63, 0x65, + 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6d, 0x61, + 0x70, 0x70, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x4f, + 0x6e, 0x6c, 0x79, 0x20, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x73, 0x20, + 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, + 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, + 0x74, 0x53, 0x41, 0x4d, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x69, 0x72, 0x65, 0x64, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x6f, 0x72, + 0x74, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x69, 0x72, + 0x65, 0x64, 0x3a, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, + 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, + 0x74, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, + 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x50, 0x61, 0x69, 0x72, 0x65, 0x64, 0x4b, 0x65, 0x65, + 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x3a, + 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x61, 0x66, + 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, + 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x70, 0x61, + 0x69, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6b, 0x65, 0x70, 0x74, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x69, + 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, + 0x46, 0x41, 0x53, 0x54, 0x51, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x70, 0x72, 0x69, 0x6d, 0x61, + 0x72, 0x79, 0x46, 0x6c, 0x61, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4f, 0x6e, 0x65, 0x42, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, + 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x70, + 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2d, 0x20, 0x61, 0x6c, 0x6c, + 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x64, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x30, 0x78, 0x31, 0x30, 0x30, 0x20, 0x62, 0x69, + 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x4c, 0x41, + 0x47, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x6e, + 0x65, 0x42, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, + 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x69, + 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x41, 0x6c, 0x6c, 0x42, 0x65, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x72, + 0x65, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x73, + 0x63, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x72, 0x69, + 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, + 0x72, 0x65, 0x61, 0x64, 0x49, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, + 0x72, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x49, 0x44, 0x20, 0x72, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, + 0x61, 0x72, 0x64, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x69, 0x72, 0x73, + 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x28, 0x75, 0x6e, 0x74, 0x69, + 0x6c, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x29, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x41, 0x53, 0x54, 0x78, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x20, 0x49, 0x44, 0x20, 0x6c, 0x69, 0x6e, 0x65, + 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x2f, + 0x31, 0x2c, 0x2f, 0x32, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x28, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x20, 0x69, + 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x41, 0x53, 0x54, 0x78, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, + 0x6d, 0x61, 0x70, 0x71, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x35, 0x35, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x30, 0x20, 0x74, 0x6f, 0x20, + 0x32, 0x35, 0x35, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x41, 0x50, + 0x51, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, + 0x72, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, + 0x61, 0x67, 0x4f, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, + 0x3a, 0x20, 0x30, 0x20, 0x74, 0x6f, 0x20, 0x36, 0x35, 0x35, 0x33, 0x35, + 0x3a, 0x20, 0x73, 0x61, 0x6d, 0x20, 0x46, 0x4c, 0x41, 0x47, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, + 0x73, 0x65, 0x20, 0x4f, 0x52, 0x27, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, + 0x20, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x46, 0x4c, 0x41, 0x47, 0x3d, 0x46, + 0x4c, 0x41, 0x47, 0x20, 0x7c, 0x20, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, + 0x66, 0x6c, 0x61, 0x67, 0x4f, 0x52, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, + 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, + 0x61, 0x67, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, + 0x6e, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x53, 0x54, 0x41, + 0x52, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x20, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, 0x61, 0x67, 0x41, + 0x4e, 0x44, 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, + 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x62, 0x69, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, - 0x61, 0x74, 0x74, 0x72, 0x52, 0x47, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x53, - 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x77, 0x6f, - 0x72, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x22, 0x49, - 0x44, 0x3a, 0x22, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x2d, 0x2d, - 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, 0x74, 0x72, 0x52, 0x47, - 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x44, 0x3a, 0x78, 0x78, 0x78, 0x20, - 0x43, 0x4e, 0x3a, 0x79, 0x79, 0x20, 0x22, 0x44, 0x53, 0x3a, 0x7a, 0x20, - 0x7a, 0x20, 0x7a, 0x22, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x78, 0x78, 0x78, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, - 0x61, 0x73, 0x20, 0x52, 0x47, 0x20, 0x74, 0x61, 0x67, 0x20, 0x74, 0x6f, - 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, - 0x41, 0x6e, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20, 0x69, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x67, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6f, - 0x20, 0x62, 0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x71, - 0x75, 0x6f, 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x61, - 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x52, - 0x47, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, - 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x29, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x49, 0x6e, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, - 0x65, 0x20, 0x73, 0x75, 0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, - 0x20, 0x62, 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2c, 0x20, - 0x65, 0x2e, 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, - 0x4d, 0x61, 0x74, 0x74, 0x72, 0x52, 0x47, 0x6c, 0x69, 0x6e, 0x65, 0x20, - 0x49, 0x44, 0x3a, 0x78, 0x78, 0x78, 0x20, 0x2c, 0x20, 0x49, 0x44, 0x3a, - 0x7a, 0x7a, 0x7a, 0x20, 0x22, 0x44, 0x53, 0x3a, 0x7a, 0x20, 0x7a, 0x22, - 0x20, 0x2c, 0x20, 0x49, 0x44, 0x3a, 0x79, 0x79, 0x79, 0x20, 0x44, 0x53, - 0x3a, 0x79, 0x79, 0x79, 0x79, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, - 0x4d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x44, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, 0x40, 0x48, - 0x44, 0x20, 0x28, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x29, 0x20, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, - 0x41, 0x4d, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0a, 0x0a, 0x6f, - 0x75, 0x74, 0x53, 0x41, 0x4d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, - 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, - 0x3a, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x40, 0x50, 0x47, 0x20, - 0x28, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x29, 0x20, 0x6c, - 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, - 0x41, 0x4d, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x28, 0x69, - 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x6f, 0x20, 0x53, 0x54, 0x41, 0x52, 0x29, 0x0a, 0x0a, 0x6f, 0x75, 0x74, - 0x53, 0x41, 0x4d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x2d, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, - 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x40, 0x43, 0x4f, - 0x20, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x6c, - 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x53, 0x41, 0x4d, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0a, 0x0a, - 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, - 0x53, 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4b, 0x65, 0x65, 0x70, 0x4f, 0x6e, 0x6c, 0x79, 0x41, 0x64, - 0x64, 0x65, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, - 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6b, - 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, - 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, - 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x46, - 0x61, 0x73, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x74, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x20, 0x73, 0x74, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, 0x65, 0x65, 0x70, - 0x41, 0x6c, 0x6c, 0x41, 0x64, 0x64, 0x65, 0x64, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x20, - 0x6b, 0x65, 0x65, 0x70, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, - 0x46, 0x61, 0x73, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, - 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x20, 0x73, 0x74, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x6f, - 0x75, 0x74, 0x53, 0x41, 0x4d, 0x6d, 0x75, 0x6c, 0x74, 0x4e, 0x6d, 0x61, - 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, - 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6d, - 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, - 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x61, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x66, 0x6c, 0x61, 0x67, 0x41, 0x4e, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x36, 0x35, 0x35, 0x33, 0x35, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x30, 0x20, 0x74, + 0x6f, 0x20, 0x36, 0x35, 0x35, 0x33, 0x35, 0x3a, 0x20, 0x73, 0x61, 0x6d, + 0x20, 0x46, 0x4c, 0x41, 0x47, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, + 0x65, 0x20, 0x62, 0x69, 0x74, 0x77, 0x69, 0x73, 0x65, 0x20, 0x41, 0x4e, + 0x44, 0x27, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x69, 0x2e, 0x65, + 0x2e, 0x20, 0x46, 0x4c, 0x41, 0x47, 0x3d, 0x46, 0x4c, 0x41, 0x47, 0x20, + 0x26, 0x20, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, 0x61, 0x67, + 0x4f, 0x52, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, + 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, + 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, + 0x74, 0x20, 0x62, 0x79, 0x20, 0x53, 0x54, 0x41, 0x52, 0x2c, 0x20, 0x62, + 0x75, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6f, 0x75, + 0x74, 0x53, 0x41, 0x4d, 0x66, 0x6c, 0x61, 0x67, 0x4f, 0x52, 0x2e, 0x20, + 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x73, 0x65, 0x74, 0x20, 0x73, 0x70, 0x65, + 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x62, 0x69, 0x74, 0x73, 0x20, 0x74, + 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x73, 0x65, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, + 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, + 0x74, 0x72, 0x52, 0x47, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x53, 0x41, 0x4d, + 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x20, 0x54, 0x68, + 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x22, 0x49, 0x44, 0x3a, + 0x22, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x2d, 0x2d, 0x6f, 0x75, + 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, 0x74, 0x72, 0x52, 0x47, 0x6c, 0x69, + 0x6e, 0x65, 0x20, 0x49, 0x44, 0x3a, 0x78, 0x78, 0x78, 0x20, 0x43, 0x4e, + 0x3a, 0x79, 0x79, 0x20, 0x22, 0x44, 0x53, 0x3a, 0x7a, 0x20, 0x7a, 0x20, + 0x7a, 0x22, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x78, 0x78, 0x78, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x61, 0x73, + 0x20, 0x52, 0x47, 0x20, 0x74, 0x61, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x65, + 0x61, 0x63, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x41, 0x6e, + 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x67, 0x20, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, + 0x65, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x20, 0x71, 0x75, 0x6f, + 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x20, 0x73, + 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x52, 0x47, 0x20, + 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, 0x66, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x29, 0x20, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, + 0x65, 0x73, 0x49, 0x6e, 0x2e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x73, + 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, + 0x73, 0x75, 0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x62, + 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x65, 0x2e, + 0x67, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, + 0x74, 0x74, 0x72, 0x52, 0x47, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x44, + 0x3a, 0x78, 0x78, 0x78, 0x20, 0x2c, 0x20, 0x49, 0x44, 0x3a, 0x7a, 0x7a, + 0x7a, 0x20, 0x22, 0x44, 0x53, 0x3a, 0x7a, 0x20, 0x7a, 0x22, 0x20, 0x2c, + 0x20, 0x49, 0x44, 0x3a, 0x79, 0x79, 0x79, 0x20, 0x44, 0x53, 0x3a, 0x79, + 0x79, 0x79, 0x79, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, 0x40, 0x48, 0x44, 0x20, + 0x28, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x29, 0x20, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0a, 0x0a, 0x6f, 0x75, 0x74, + 0x53, 0x41, 0x4d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x47, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, + 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x40, 0x50, 0x47, 0x20, 0x28, 0x73, + 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x29, 0x20, 0x6c, 0x69, 0x6e, + 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x28, 0x69, 0x6e, 0x20, + 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, + 0x53, 0x54, 0x41, 0x52, 0x29, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, + 0x4d, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x61, 0x74, + 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x40, 0x43, 0x4f, 0x20, 0x28, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x6c, 0x69, 0x6e, + 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, + 0x4d, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x0a, 0x0a, 0x6f, 0x75, + 0x74, 0x53, 0x41, 0x4d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, + 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x41, + 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4b, 0x65, 0x65, 0x70, 0x4f, 0x6e, 0x6c, 0x79, 0x41, 0x64, 0x64, 0x65, + 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6b, 0x65, 0x65, + 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x6c, + 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x46, 0x61, 0x73, + 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, + 0x6c, 0x41, 0x64, 0x64, 0x65, 0x64, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x20, 0x6b, 0x65, + 0x65, 0x70, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, + 0x65, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x2d, 0x2d, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x46, 0x61, + 0x73, 0x74, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, + 0x73, 0x74, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x6f, 0x75, 0x74, + 0x53, 0x41, 0x4d, 0x6d, 0x75, 0x6c, 0x74, 0x4e, 0x6d, 0x61, 0x78, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6d, 0x61, 0x78, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, + 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x20, + 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x66, + 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, + 0x20, 0x74, 0x6f, 0x20, 0x2d, 0x31, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x6f, 0x70, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, + 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x20, 0x28, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, + 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, - 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2d, 0x31, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, - 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, - 0x28, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, - 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, - 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x0a, - 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x6c, 0x65, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x63, - 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x54, 0x4c, 0x45, 0x4e, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x2f, - 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x6d, 0x6f, 0x73, 0x74, - 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x28, 0x2b, 0x29, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6d, - 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x28, 0x2d, 0x29, 0x6d, 0x61, 0x74, 0x65, - 0x2e, 0x20, 0x28, 0x2b, 0x29, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x28, 0x2b, 0x29, 0x73, 0x74, 0x72, - 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x6d, 0x6f, 0x73, 0x74, 0x20, - 0x62, 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, - 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x69, 0x67, 0x68, + 0x70, 0x75, 0x74, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, + 0x6c, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, + 0x6e, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x4c, 0x45, 0x4e, 0x20, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x53, 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x31, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x6f, - 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, - 0x28, 0x2b, 0x29, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x6d, 0x6f, - 0x73, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x69, - 0x73, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x31, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x70, 0x72, 0x6f, 0x74, 0x72, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, - 0x65, 0x6e, 0x64, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x42, 0x41, 0x4d, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x28, 0x2b, 0x29, 0x73, 0x74, 0x72, + 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, + 0x72, 0x69, 0x67, 0x68, 0x74, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x62, 0x61, + 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x28, 0x2d, + 0x29, 0x6d, 0x61, 0x74, 0x65, 0x2e, 0x20, 0x28, 0x2b, 0x29, 0x73, 0x69, + 0x67, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x28, + 0x2b, 0x29, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, + 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x32, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6c, 0x65, 0x66, 0x74, + 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x62, + 0x61, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, + 0x61, 0x74, 0x65, 0x2e, 0x20, 0x28, 0x2b, 0x29, 0x73, 0x69, 0x67, 0x6e, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x74, + 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, + 0x65, 0x66, 0x74, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, + 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, + 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, + 0x20, 0x31, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x72, 0x75, + 0x64, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x0a, 0x0a, 0x6f, + 0x75, 0x74, 0x42, 0x41, 0x4d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x2d, 0x31, + 0x20, 0x74, 0x6f, 0x20, 0x31, 0x30, 0x20, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x2d, 0x31, 0x20, 0x74, 0x6f, 0x20, 0x31, - 0x30, 0x20, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x2c, 0x20, 0x2d, 0x31, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x28, 0x36, 0x3f, 0x29, 0x2c, 0x20, 0x30, 0x3d, 0x6e, 0x6f, 0x20, - 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, - 0x20, 0x31, 0x30, 0x3d, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x0a, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x2c, 0x20, 0x2d, 0x31, 0x3d, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x36, 0x3f, 0x29, 0x2c, 0x20, + 0x30, 0x3d, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x31, 0x30, 0x3d, 0x6d, 0x61, 0x78, + 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x42, 0x41, 0x4d, + 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x64, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, + 0x61, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x42, 0x41, 0x4d, 0x20, + 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x30, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, + 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x36, 0x2c, 0x2d, 0x2d, 0x72, + 0x75, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4e, 0x29, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x42, 0x41, 0x4d, 0x73, 0x6f, 0x72, 0x74, 0x69, - 0x6e, 0x67, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4e, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, - 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, - 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x69, - 0x6e, 0x67, 0x2e, 0x20, 0x30, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x69, - 0x6e, 0x28, 0x36, 0x2c, 0x2d, 0x2d, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x72, - 0x65, 0x61, 0x64, 0x4e, 0x29, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x42, - 0x41, 0x4d, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x69, 0x6e, - 0x73, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x3e, 0x30, 0x3a, 0x20, - 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x67, - 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x73, 0x20, 0x66, - 0x6f, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, - 0x2d, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x23, 0x23, - 0x23, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x69, 0x6e, 0x67, 0x0a, 0x62, 0x61, 0x6d, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, - 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6d, 0x61, 0x72, 0x6b, - 0x20, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, - 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x77, - 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x28, 0x69, 0x29, 0x20, 0x73, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x65, 0x64, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x42, 0x41, - 0x4d, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, - 0x69, 0x69, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x69, 0x72, - 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, + 0x6e, 0x67, 0x42, 0x69, 0x6e, 0x73, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x35, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, + 0x20, 0x3e, 0x30, 0x3a, 0x20, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x20, 0x6f, 0x66, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x62, + 0x69, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, + 0x69, 0x6e, 0x61, 0x74, 0x65, 0x2d, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, + 0x67, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x0a, 0x62, 0x61, + 0x6d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x73, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x2d, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x28, 0x69, + 0x29, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x42, 0x41, 0x4d, + 0x20, 0x66, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x6e, + 0x70, 0x75, 0x74, 0x42, 0x41, 0x4d, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x28, 0x69, 0x69, 0x29, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x64, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x2f, - 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x71, - 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, - 0x65, 0x72, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6f, - 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x46, 0x4c, - 0x41, 0x47, 0x2c, 0x20, 0x43, 0x49, 0x47, 0x41, 0x52, 0x20, 0x6d, 0x75, - 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x72, - 0x6b, 0x20, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, - 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, - 0x72, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, - 0x0a, 0x0a, 0x62, 0x61, 0x6d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, - 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x4d, 0x61, 0x74, - 0x65, 0x32, 0x62, 0x61, 0x73, 0x65, 0x73, 0x4e, 0x20, 0x20, 0x20, 0x30, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x35, 0x27, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, - 0x32, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, - 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x28, - 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x52, 0x41, 0x4d, - 0x50, 0x41, 0x47, 0x45, 0x29, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x57, 0x69, 0x67, 0x67, 0x6c, 0x65, - 0x0a, 0x6f, 0x75, 0x74, 0x57, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, - 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x28, 0x73, 0x29, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, - 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x22, 0x62, 0x65, - 0x64, 0x47, 0x72, 0x61, 0x70, 0x68, 0x22, 0x20, 0x4f, 0x52, 0x20, 0x22, - 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, 0x68, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x31, 0x5f, 0x35, 0x70, 0x22, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x73, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, - 0x42, 0x41, 0x4d, 0x3a, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, - 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x53, 0x6f, - 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, - 0x6e, 0x61, 0x74, 0x65, 0x20, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x31, 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x64, + 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x6e, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, 0x68, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, 0x68, - 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x77, 0x69, 0x67, 0x67, 0x6c, - 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, - 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x31, 0x5f, 0x35, 0x70, 0x20, 0x20, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x35, 0x27, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x43, 0x41, 0x47, 0x45, 0x2f, 0x52, 0x41, 0x4d, 0x50, 0x41, - 0x47, 0x45, 0x20, 0x65, 0x74, 0x63, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x64, 0x32, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, - 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x32, - 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x0a, 0x0a, 0x6f, 0x75, 0x74, - 0x57, 0x69, 0x67, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, - 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x3a, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x6e, 0x65, - 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x69, 0x67, 0x67, 0x6c, 0x65, - 0x2f, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, 0x68, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, - 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x73, - 0x74, 0x72, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x72, 0x32, + 0x20, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x61, 0x6c, + 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, 0x65, + 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x75, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, + 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x54, 0x68, + 0x65, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, + 0x73, 0x2c, 0x20, 0x46, 0x4c, 0x41, 0x47, 0x2c, 0x20, 0x43, 0x49, 0x47, + 0x41, 0x52, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, + 0x71, 0x75, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x6c, + 0x4e, 0x6f, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x20, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x64, 0x75, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, + 0x6d, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, + 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, + 0x70, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x0a, 0x62, 0x61, 0x6d, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x73, 0x4d, 0x61, 0x74, 0x65, 0x32, 0x62, 0x61, 0x73, 0x65, 0x73, + 0x4e, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, + 0x6f, 0x66, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x35, 0x27, 0x20, 0x6f, 0x66, 0x20, + 0x6d, 0x61, 0x74, 0x65, 0x20, 0x32, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, + 0x65, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, + 0x69, 0x6e, 0x67, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x52, 0x41, 0x4d, 0x50, 0x41, 0x47, 0x45, 0x29, 0x0a, 0x0a, + 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x57, + 0x69, 0x67, 0x67, 0x6c, 0x65, 0x0a, 0x6f, 0x75, 0x74, 0x57, 0x69, 0x67, + 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x65, 0x2e, 0x67, + 0x2e, 0x20, 0x22, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, 0x68, 0x22, + 0x20, 0x4f, 0x52, 0x20, 0x22, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x20, 0x72, 0x65, 0x61, 0x64, 0x31, 0x5f, 0x35, 0x70, 0x22, 0x2e, + 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x73, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x20, 0x42, 0x41, 0x4d, 0x3a, 0x20, 0x2d, 0x2d, + 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x42, + 0x41, 0x4d, 0x20, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, + 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x73, 0x74, 0x20, + 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x65, 0x64, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x73, - 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x73, - 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x57, - 0x69, 0x67, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, - 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, - 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, - 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x77, 0x69, 0x67, - 0x67, 0x6c, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x65, 0x2e, - 0x67, 0x2e, 0x20, 0x22, 0x63, 0x68, 0x72, 0x22, 0x2c, 0x20, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x22, 0x2d, 0x22, 0x20, 0x2d, 0x20, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x0a, - 0x6f, 0x75, 0x74, 0x57, 0x69, 0x67, 0x4e, 0x6f, 0x72, 0x6d, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x52, 0x50, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x50, 0x4d, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x70, 0x65, - 0x72, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, - 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, - 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x6e, 0x6f, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x22, 0x72, 0x61, 0x77, 0x22, - 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x0a, 0x0a, 0x23, 0x23, 0x23, - 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x67, + 0x67, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x77, 0x69, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, + 0x64, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x64, 0x31, 0x5f, 0x35, 0x70, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, + 0x35, 0x27, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, 0x73, + 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x66, + 0x75, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x43, 0x41, 0x47, 0x45, 0x2f, + 0x52, 0x41, 0x4d, 0x50, 0x41, 0x47, 0x45, 0x20, 0x65, 0x74, 0x63, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x57, 0x69, 0x67, 0x53, 0x74, 0x72, 0x61, + 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, + 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, + 0x64, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x77, + 0x69, 0x67, 0x67, 0x6c, 0x65, 0x2f, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, + 0x65, 0x64, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x20, 0x73, 0x65, + 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, + 0x64, 0x73, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x31, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x73, 0x74, 0x72, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x55, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, + 0x73, 0x65, 0x64, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x57, 0x69, 0x67, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, + 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x20, 0x77, 0x69, 0x67, 0x67, 0x6c, 0x65, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x22, 0x63, 0x68, 0x72, + 0x22, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x22, + 0x2d, 0x22, 0x20, 0x2d, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x57, 0x69, 0x67, 0x4e, + 0x6f, 0x72, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x50, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, - 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, - 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, - 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x50, + 0x4d, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, + 0x64, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, + 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x79, 0x53, 0x4a, 0x6f, - 0x75, 0x74, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, - 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x73, - 0x73, 0x65, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x4a, 0x2e, 0x6f, 0x75, - 0x74, 0x2e, 0x74, 0x61, 0x62, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, - 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, - 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x77, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x0a, 0x6f, - 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x75, 0x6c, 0x74, - 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, - 0x75, 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, - 0x20, 0x6c, 0x6f, 0x63, 0x69, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x74, 0x6f, 0x2e, - 0x20, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, - 0x28, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, - 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, - 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, - 0x65, 0x20, 0x6c, 0x6f, 0x63, 0x69, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x74, 0x68, - 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x22, 0x6d, 0x61, - 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x6f, 0x6f, 0x20, - 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x6f, 0x63, 0x69, 0x22, 0x20, 0x69, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x6f, 0x67, 0x2e, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x2e, 0x6f, 0x75, 0x74, 0x20, 0x2e, 0x0a, 0x0a, 0x6f, - 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x69, 0x73, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x6e, 0x6f, 0x72, + 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, + 0x22, 0x72, 0x61, 0x77, 0x22, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x6f, + 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, + 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, + 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, + 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x42, 0x79, 0x53, 0x4a, 0x6f, 0x75, 0x74, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x6b, 0x65, 0x65, 0x70, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, + 0x6f, 0x73, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6a, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, + 0x53, 0x4a, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x74, 0x61, 0x62, 0x0a, 0x0a, + 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x75, 0x6c, + 0x74, 0x69, 0x6d, 0x61, 0x70, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x63, 0x6f, 0x72, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x62, + 0x65, 0x6c, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x78, + 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, + 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, + 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x6f, 0x63, 0x69, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, + 0x70, 0x20, 0x74, 0x6f, 0x2e, 0x20, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x20, 0x28, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x6d, 0x29, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, + 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x20, 0x6d, 0x61, 0x70, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6e, + 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6c, 0x6f, 0x63, 0x69, 0x20, + 0x74, 0x68, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, + 0x6e, 0x6f, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, + 0x73, 0x20, 0x22, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x6f, + 0x63, 0x69, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, + 0x6f, 0x67, 0x2e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x6f, 0x75, 0x74, + 0x20, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x61, + 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, + 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x20, + 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, + 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, + 0x68, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, + 0x76, 0x65, 0x72, 0x4c, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x30, 0x2e, 0x33, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, + 0x6c, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, + 0x69, 0x74, 0x73, 0x20, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x20, 0x6f, 0x66, + 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, + 0x74, 0x6f, 0x20, 0x2a, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x2a, 0x20, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x65, + 0x73, 0x73, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, + 0x71, 0x75, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x4e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x4c, + 0x6d, 0x61, 0x78, 0x20, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x72, 0x65, 0x61, 0x6c, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, + 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, + 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, + 0x68, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x72, 0x65, 0x61, 0x64, + 0x2a, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, + 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x72, + 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, + 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x63, 0x6f, + 0x72, 0x65, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, - 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, - 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x74, - 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x0a, - 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x69, 0x73, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x76, 0x65, 0x72, 0x4c, 0x6d, - 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x33, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x3a, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, - 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, - 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x2a, 0x6d, - 0x61, 0x70, 0x70, 0x65, 0x64, 0x2a, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, - 0x61, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x6d, 0x61, 0x78, 0x20, 0x20, - 0x31, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x6c, - 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x69, - 0x74, 0x73, 0x20, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x20, 0x6f, 0x66, 0x20, - 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x2a, 0x72, 0x65, 0x61, 0x64, 0x2a, 0x20, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x20, + 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x20, 0x69, 0x73, 0x20, 0x68, 0x69, 0x67, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x4d, 0x69, 0x6e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, - 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x69, - 0x74, 0x73, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, + 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x4d, 0x69, 0x6e, 0x4f, + 0x76, 0x65, 0x72, 0x4c, 0x72, 0x65, 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x30, 0x2e, 0x36, 0x36, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, + 0x65, 0x61, 0x6c, 0x3a, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, + 0x20, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x63, + 0x6f, 0x72, 0x65, 0x4d, 0x69, 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, + 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x20, 0x28, 0x73, 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x6d, + 0x61, 0x74, 0x65, 0x73, 0x27, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, + 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x29, 0x0a, + 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, + 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, + 0x79, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x69, 0x73, 0x20, 0x68, 0x69, 0x67, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, - 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x63, - 0x6f, 0x72, 0x65, 0x4d, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x4c, 0x72, - 0x65, 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x36, + 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x61, + 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x4c, + 0x72, 0x65, 0x61, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x36, 0x36, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x3a, 0x20, - 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x4d, 0x69, - 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x20, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x28, 0x73, - 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x27, - 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x64, 0x20, - 0x72, 0x65, 0x61, 0x64, 0x73, 0x29, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, - 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, - 0x74, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, - 0x66, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x20, 0x69, 0x73, 0x20, 0x68, 0x69, 0x67, 0x68, 0x65, - 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x71, - 0x75, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, - 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x4c, 0x72, 0x65, 0x61, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x36, 0x36, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x61, 0x6c, 0x3a, 0x20, 0x73, 0x61, 0x6d, 0x20, 0x61, - 0x73, 0x20, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4d, - 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x69, 0x6e, 0x2c, 0x20, 0x62, 0x75, - 0x74, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, - 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x28, 0x73, 0x75, 0x6d, - 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x27, 0x20, 0x6c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, - 0x61, 0x69, 0x72, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x73, 0x29, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x4d, 0x6f, - 0x74, 0x69, 0x66, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, - 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x0a, 0x09, 0x09, 0x09, 0x09, - 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, - 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x0a, - 0x09, 0x09, 0x09, 0x09, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, - 0x6e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, - 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, - 0x63, 0x61, 0x6c, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4e, 0x6f, 0x6e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, - 0x55, 0x6e, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, - 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, - 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x75, 0x6e, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x75, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, - 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6a, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, - 0x65, 0x20, 0x6b, 0x65, 0x70, 0x74, 0x2e, 0x0a, 0x0a, 0x6f, 0x75, 0x74, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x6e, - 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, - 0x6e, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x73, 0x61, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x69, + 0x6e, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, + 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x20, 0x28, 0x73, 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x74, + 0x65, 0x73, 0x27, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x73, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x2d, 0x65, + 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x29, 0x2e, 0x0a, 0x0a, + 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x74, + 0x72, 0x6f, 0x6e, 0x4d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, + 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, - 0x6e, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, - 0x6e, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x20, - 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, - 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x0a, - 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, - 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x53, - 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x73, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x41, 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, - 0x64, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6c, 0x6c, - 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, - 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, - 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, - 0x6c, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, - 0x2c, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, 0x61, 0x70, 0x70, - 0x65, 0x72, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x71, - 0x75, 0x65, 0x3a, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x79, - 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x0a, 0x6f, 0x75, 0x74, - 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x76, 0x65, 0x72, - 0x68, 0x61, 0x6e, 0x67, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x30, 0x20, 0x20, 0x31, 0x32, 0x20, - 0x20, 0x31, 0x32, 0x20, 0x20, 0x31, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x34, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x3a, 0x20, - 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, - 0x76, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, 0x20, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, - 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x6f, 0x6e, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x73, 0x69, 0x64, 0x65, - 0x73, 0x20, 0x66, 0x6f, 0x72, 0x3a, 0x20, 0x28, 0x31, 0x29, 0x20, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, + 0x63, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, + 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6a, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x61, 0x6e, 0x6f, + 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x6e, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, + 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x75, + 0x6e, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65, + 0x6e, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x65, + 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, - 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x2c, 0x20, 0x28, 0x32, 0x29, - 0x20, 0x47, 0x54, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, - 0x54, 0x2f, 0x41, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2c, 0x20, - 0x28, 0x33, 0x29, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, - 0x66, 0x2c, 0x20, 0x28, 0x34, 0x29, 0x20, 0x41, 0x54, 0x2f, 0x41, 0x43, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, 0x20, 0x6d, - 0x6f, 0x74, 0x69, 0x66, 0x2e, 0x20, 0x2d, 0x31, 0x20, 0x6d, 0x65, 0x61, - 0x6e, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, - 0x74, 0x69, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6b, 0x65, 0x70, 0x74, 0x2e, + 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, + 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x73, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x70, 0x70, - 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, - 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x69, 0x71, 0x75, - 0x65, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, - 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x31, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, - 0x65, 0x72, 0x73, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, - 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x79, 0x20, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x65, 0x72, 0x20, 0x6a, 0x75, 0x6e, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x3a, 0x20, 0x28, - 0x31, 0x29, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, - 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x2c, - 0x20, 0x28, 0x32, 0x29, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x47, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x43, 0x54, 0x2f, 0x41, 0x43, 0x20, 0x6d, 0x6f, 0x74, - 0x69, 0x66, 0x2c, 0x20, 0x28, 0x33, 0x29, 0x20, 0x47, 0x43, 0x2f, 0x41, - 0x47, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, - 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2c, 0x20, 0x28, 0x34, 0x29, 0x20, 0x41, - 0x54, 0x2f, 0x41, 0x43, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, - 0x41, 0x54, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2e, 0x20, 0x2d, 0x31, - 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, - 0x20, 0x69, 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, - 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4d, 0x69, 0x6e, - 0x20, 0x4f, 0x52, 0x20, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x74, 0x61, - 0x6c, 0x4d, 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x61, 0x74, 0x69, - 0x73, 0x66, 0x69, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, + 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x28, 0x53, + 0x4a, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x74, 0x61, 0x62, 0x29, 0x0a, 0x6f, + 0x75, 0x74, 0x53, 0x4a, 0x74, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, + 0x61, 0x72, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, - 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x74, - 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, + 0x61, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, + 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x53, 0x4a, 0x2e, 0x6f, + 0x75, 0x74, 0x2e, 0x74, 0x61, 0x62, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, + 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, + 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x53, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x4a, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x6f, 0x75, 0x74, 0x53, + 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x73, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x63, + 0x68, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x73, 0x70, + 0x6c, 0x69, 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x73, 0x2c, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2d, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, + 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x79, 0x20, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, + 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x76, 0x65, 0x72, 0x68, + 0x61, 0x6e, 0x67, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x33, 0x30, 0x20, 0x20, 0x31, 0x32, 0x20, 0x20, + 0x31, 0x32, 0x20, 0x20, 0x31, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, + 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x20, + 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, 0x76, + 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, + 0x6e, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x73, 0x69, 0x64, 0x65, 0x73, + 0x20, 0x66, 0x6f, 0x72, 0x3a, 0x20, 0x28, 0x31, 0x29, 0x20, 0x6e, 0x6f, + 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, + 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x2c, 0x20, 0x28, 0x32, 0x29, 0x20, + 0x47, 0x54, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x54, + 0x2f, 0x41, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2c, 0x20, 0x28, + 0x33, 0x29, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, + 0x2c, 0x20, 0x28, 0x34, 0x29, 0x20, 0x41, 0x54, 0x2f, 0x41, 0x43, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, 0x20, 0x6d, 0x6f, + 0x74, 0x69, 0x66, 0x2e, 0x20, 0x2d, 0x31, 0x20, 0x6d, 0x65, 0x61, 0x6e, + 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x74, + 0x69, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, + 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6c, + 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, + 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x20, 0x28, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2b, 0x75, 0x6e, 0x69, - 0x71, 0x75, 0x65, 0x29, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, 0x6f, + 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x79, 0x20, 0x6d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x70, 0x65, 0x72, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x3a, 0x20, 0x28, 0x31, 0x29, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, @@ -2053,137 +2609,177 @@ unsigned char parametersDefault[] = { 0x70, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x44, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x4f, 0x74, 0x68, - 0x65, 0x72, 0x53, 0x4a, 0x6d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x31, 0x30, 0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x35, 0x20, 0x20, 0x20, - 0x31, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, 0x20, 0x69, 0x6e, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x73, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x69, - 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, - 0x6f, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6a, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x64, 0x6f, 0x6e, 0x6f, 0x72, - 0x2f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, - 0x6f, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, - 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x72, - 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x56, 0x73, 0x52, 0x65, 0x61, 0x64, 0x4e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x30, 0x30, - 0x30, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x32, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x20, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6d, - 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x67, 0x61, 0x70, 0x20, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6a, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x31, 0x2c, - 0x32, 0x2c, 0x33, 0x2c, 0x2c, 0x2c, 0x4e, 0x20, 0x72, 0x65, 0x61, 0x64, - 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x74, 0x61, + 0x6c, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x20, 0x20, + 0x20, 0x31, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x34, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, + 0x73, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x20, 0x28, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2b, 0x75, 0x6e, 0x69, 0x71, + 0x75, 0x65, 0x29, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x20, 0x70, 0x65, 0x72, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x3a, 0x20, 0x28, 0x31, 0x29, + 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, + 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x2c, 0x20, 0x28, + 0x32, 0x29, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x43, 0x54, 0x2f, 0x41, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, + 0x2c, 0x20, 0x28, 0x33, 0x29, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, 0x6d, 0x6f, + 0x74, 0x69, 0x66, 0x2c, 0x20, 0x28, 0x34, 0x29, 0x20, 0x41, 0x54, 0x2f, + 0x41, 0x43, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, + 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2e, 0x20, 0x2d, 0x31, 0x20, 0x6d, + 0x65, 0x61, 0x6e, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x69, + 0x66, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x75, 0x74, + 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4d, 0x69, 0x6e, 0x20, 0x4f, + 0x52, 0x20, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4d, + 0x69, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, + 0x69, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x2e, - 0x65, 0x2e, 0x20, 0x62, 0x79, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, - 0x20, 0x31, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, 0x61, 0x6e, 0x20, - 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x61, 0x70, 0x73, 0x20, 0x3c, 0x3d, - 0x35, 0x30, 0x30, 0x30, 0x30, 0x62, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x32, - 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x20, 0x3c, 0x3d, 0x31, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x62, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x33, 0x20, - 0x72, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x20, 0x3c, 0x3d, 0x32, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x2e, 0x20, 0x62, 0x79, 0x20, 0x3e, 0x3d, 0x34, 0x20, - 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x67, 0x61, - 0x70, 0x20, 0x3c, 0x3d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x74, - 0x72, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, - 0x61, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, - 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x53, 0x63, - 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x47, - 0x61, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x73, 0x70, - 0x6c, 0x69, 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x20, 0x28, 0x69, - 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x20, 0x6f, - 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x6d, 0x6f, 0x74, - 0x69, 0x66, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x47, 0x61, - 0x70, 0x4e, 0x6f, 0x6e, 0x63, 0x61, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x38, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6e, 0x6f, - 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, - 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, - 0x61, 0x6c, 0x74, 0x79, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, - 0x72, 0x65, 0x47, 0x61, 0x70, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, - 0x65, 0x47, 0x61, 0x70, 0x47, 0x43, 0x41, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2d, 0x34, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x47, 0x43, 0x2f, 0x41, - 0x47, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, + 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x70, 0x70, + 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, 0x4a, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x44, 0x69, 0x73, 0x74, 0x54, 0x6f, 0x4f, 0x74, 0x68, 0x65, + 0x72, 0x53, 0x4a, 0x6d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x30, 0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x35, 0x20, 0x20, 0x20, 0x31, + 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, 0x20, 0x69, 0x6e, 0x74, 0x65, + 0x67, 0x65, 0x72, 0x73, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, + 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x64, 0x6f, 0x6e, 0x6f, 0x72, 0x2f, + 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, + 0x74, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x6f, 0x75, 0x74, 0x53, + 0x4a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x72, 0x6f, + 0x6e, 0x4d, 0x61, 0x78, 0x56, 0x73, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x30, 0x30, 0x30, + 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x32, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x65, 0x72, 0x73, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x61, + 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x67, 0x61, 0x70, 0x20, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6a, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x31, 0x2c, 0x32, + 0x2c, 0x33, 0x2c, 0x2c, 0x2c, 0x4e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x2e, 0x65, + 0x2e, 0x20, 0x62, 0x79, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, + 0x31, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x68, + 0x61, 0x76, 0x65, 0x20, 0x67, 0x61, 0x70, 0x73, 0x20, 0x3c, 0x3d, 0x35, + 0x30, 0x30, 0x30, 0x30, 0x62, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x32, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x20, 0x3c, 0x3d, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x62, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x33, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x73, 0x3a, 0x20, 0x3c, 0x3d, 0x32, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x2e, 0x20, 0x62, 0x79, 0x20, 0x3e, 0x3d, 0x34, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x67, 0x61, 0x70, + 0x20, 0x3c, 0x3d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x74, 0x72, + 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, + 0x70, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x53, 0x63, 0x6f, + 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x47, 0x61, + 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x73, 0x70, 0x6c, + 0x69, 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x20, 0x28, 0x69, 0x6e, + 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, + 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x6d, 0x6f, 0x74, 0x69, + 0x66, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x47, 0x61, 0x70, + 0x4e, 0x6f, 0x6e, 0x63, 0x61, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x38, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, + 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x6a, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, + 0x6c, 0x74, 0x79, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x47, 0x61, 0x70, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x47, 0x61, 0x70, 0x47, 0x43, 0x41, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2d, 0x34, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, 0x6a, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, + 0x6c, 0x74, 0x79, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x47, 0x61, 0x70, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x47, 0x61, 0x70, 0x41, 0x54, 0x41, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2d, 0x38, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x41, 0x54, 0x2f, 0x41, 0x43, + 0x20, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, - 0x61, 0x6c, 0x74, 0x79, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, - 0x72, 0x65, 0x47, 0x61, 0x70, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, - 0x65, 0x47, 0x61, 0x70, 0x41, 0x54, 0x41, 0x43, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2d, 0x38, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x41, 0x54, 0x2f, 0x41, - 0x43, 0x20, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, - 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, - 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x20, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, - 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, - 0x63, 0x6f, 0x72, 0x65, 0x47, 0x61, 0x70, 0x29, 0x0a, 0x0a, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x4c, 0x6f, 0x67, 0x32, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x20, 0x20, 0x20, 0x2d, 0x30, 0x2e, 0x32, 0x35, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x73, 0x63, 0x6f, 0x72, - 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x69, - 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, - 0x63, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x3a, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x47, 0x65, 0x6e, 0x6f, - 0x6d, 0x69, 0x63, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4c, 0x6f, 0x67, - 0x32, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2a, 0x6c, 0x6f, 0x67, 0x32, 0x28, - 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x44, 0x65, 0x6c, - 0x4f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x32, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, - 0x79, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x44, 0x65, 0x6c, 0x42, - 0x61, 0x73, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x61, 0x6c, 0x74, 0x79, 0x20, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, + 0x6f, 0x72, 0x65, 0x47, 0x61, 0x70, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, + 0x72, 0x65, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x4c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x4c, 0x6f, 0x67, 0x32, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x20, 0x20, 0x20, 0x2d, 0x30, 0x2e, 0x32, 0x35, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x20, 0x6c, 0x6f, 0x67, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x69, 0x63, + 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, + 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x3a, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x47, 0x65, 0x6e, 0x6f, 0x6d, + 0x69, 0x63, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4c, 0x6f, 0x67, 0x32, + 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2a, 0x6c, 0x6f, 0x67, 0x32, 0x28, 0x67, + 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x44, 0x65, 0x6c, 0x4f, + 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, - 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x20, 0x70, 0x65, 0x72, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, - 0x44, 0x65, 0x6c, 0x4f, 0x70, 0x65, 0x6e, 0x29, 0x0a, 0x0a, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2d, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, - 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x70, 0x65, 0x6e, - 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x0a, 0x0a, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x73, 0x42, 0x61, 0x73, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2d, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, - 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x78, 0x74, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, - 0x79, 0x20, 0x70, 0x65, 0x72, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x28, - 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x73, 0x4f, - 0x70, 0x65, 0x6e, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x53, - 0x74, 0x69, 0x74, 0x63, 0x68, 0x53, 0x4a, 0x73, 0x68, 0x69, 0x66, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, - 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x72, 0x65, 0x64, 0x75, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x73, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x53, 0x4a, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x69, - 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x69, + 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, + 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x44, 0x65, 0x6c, 0x42, 0x61, + 0x73, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x32, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, + 0x61, 0x6c, 0x74, 0x79, 0x20, 0x70, 0x65, 0x72, 0x20, 0x62, 0x61, 0x73, + 0x65, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x44, + 0x65, 0x6c, 0x4f, 0x70, 0x65, 0x6e, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, + 0x72, 0x65, 0x49, 0x6e, 0x73, 0x4f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2d, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x73, + 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, + 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x0a, 0x0a, 0x73, 0x63, 0x6f, + 0x72, 0x65, 0x49, 0x6e, 0x73, 0x42, 0x61, 0x73, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2d, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x73, + 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, + 0x20, 0x70, 0x65, 0x72, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x28, 0x69, + 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x73, 0x4f, 0x70, + 0x65, 0x6e, 0x29, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x53, 0x74, + 0x69, 0x74, 0x63, 0x68, 0x53, 0x4a, 0x73, 0x68, 0x69, 0x66, 0x74, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, + 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x72, 0x65, 0x64, 0x75, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x53, 0x4a, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x69, 0x65, + 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x69, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x65, 0x70, 0x0a, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x65, @@ -2218,9 +2814,9 @@ unsigned char parametersDefault[] = { 0x6e, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x73, 0x2c, - 0x20, 0x69, 0x66, 0x20, 0x3d, 0x30, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x73, - 0x65, 0x65, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x69, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x0a, 0x0a, 0x73, + 0x20, 0x69, 0x66, 0x20, 0x3d, 0x30, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, + 0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x0a, 0x0a, 0x73, 0x65, 0x65, 0x64, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, @@ -2257,390 +2853,396 @@ unsigned char parametersDefault[] = { 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x20, 0x62, 0x79, 0x20, 0x4e, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, - 0x67, 0x61, 0x70, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, - 0x74, 0x72, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x31, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3a, - 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x67, 0x61, 0x70, - 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, - 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x69, 0x66, - 0x20, 0x69, 0x74, 0x73, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3e, - 0x3d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x6e, - 0x4d, 0x69, 0x6e, 0x2c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, - 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, - 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, - 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, - 0x20, 0x69, 0x66, 0x20, 0x30, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x69, - 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x77, - 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x28, 0x32, 0x5e, - 0x77, 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x4e, 0x62, 0x69, 0x74, 0x73, 0x29, - 0x2a, 0x77, 0x69, 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x69, - 0x73, 0x74, 0x4e, 0x62, 0x69, 0x6e, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x4d, 0x61, 0x74, 0x65, 0x73, 0x47, 0x61, 0x70, 0x4d, 0x61, - 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, - 0x75, 0x6d, 0x20, 0x67, 0x61, 0x70, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, - 0x65, 0x6e, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, - 0x2c, 0x20, 0x69, 0x66, 0x20, 0x30, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x20, - 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x67, 0x61, 0x70, 0x20, 0x77, - 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x28, 0x32, 0x5e, - 0x77, 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x4e, 0x62, 0x69, 0x74, 0x73, 0x29, - 0x2a, 0x77, 0x69, 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x69, - 0x73, 0x74, 0x4e, 0x62, 0x69, 0x6e, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x53, 0x4a, 0x6f, 0x76, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, + 0x67, 0x61, 0x70, 0x0a, 0x0a, 0x73, 0x65, 0x65, 0x64, 0x4d, 0x61, 0x70, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x35, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, - 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, 0x76, - 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, - 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x64, - 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, - 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x4a, 0x73, 0x74, 0x69, 0x74, - 0x63, 0x68, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, - 0x61, 0x78, 0x20, 0x20, 0x20, 0x30, 0x20, 0x2d, 0x31, 0x20, 0x30, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, 0x2a, 0x69, 0x6e, 0x74, 0x3e, - 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, - 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x73, 0x74, 0x69, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, - 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x28, - 0x2d, 0x31, 0x3a, 0x20, 0x6e, 0x6f, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, + 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x20, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x65, 0x64, + 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, + 0x65, 0x64, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x74, + 0x72, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x31, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x69, + 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, + 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x67, 0x61, 0x70, 0x20, + 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, + 0x64, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x69, 0x66, 0x20, + 0x69, 0x74, 0x73, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3e, 0x3d, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x4d, + 0x69, 0x6e, 0x2c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77, 0x69, 0x73, + 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, + 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, + 0x74, 0x72, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x69, + 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2c, 0x20, + 0x69, 0x66, 0x20, 0x30, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x69, 0x6e, + 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x77, 0x69, + 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x28, 0x32, 0x5e, 0x77, + 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x4e, 0x62, 0x69, 0x74, 0x73, 0x29, 0x2a, + 0x77, 0x69, 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x69, 0x73, + 0x74, 0x4e, 0x62, 0x69, 0x6e, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x4d, 0x61, 0x74, 0x65, 0x73, 0x47, 0x61, 0x70, 0x4d, 0x61, 0x78, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, + 0x6d, 0x20, 0x67, 0x61, 0x70, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, + 0x6e, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x2c, + 0x20, 0x69, 0x66, 0x20, 0x30, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x69, + 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x67, 0x61, 0x70, 0x20, 0x77, 0x69, + 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x28, 0x32, 0x5e, 0x77, + 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x4e, 0x62, 0x69, 0x74, 0x73, 0x29, 0x2a, + 0x77, 0x69, 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x69, 0x73, + 0x74, 0x4e, 0x62, 0x69, 0x6e, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x53, 0x4a, 0x6f, 0x76, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, 0x4d, + 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x35, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, + 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, 0x76, 0x65, + 0x72, 0x68, 0x61, 0x6e, 0x67, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x0a, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x4a, 0x73, 0x74, 0x69, 0x74, 0x63, + 0x68, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6d, 0x61, + 0x78, 0x20, 0x20, 0x20, 0x30, 0x20, 0x2d, 0x31, 0x20, 0x30, 0x20, 0x30, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x34, 0x2a, 0x69, 0x6e, 0x74, 0x3e, 0x3d, + 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x73, 0x74, 0x69, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, + 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x28, 0x2d, + 0x31, 0x3a, 0x20, 0x6e, 0x6f, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x29, + 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x31, 0x29, 0x20, 0x6e, - 0x6f, 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, - 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x2c, 0x20, 0x28, 0x32, 0x29, - 0x20, 0x47, 0x54, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, - 0x54, 0x2f, 0x41, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2c, 0x20, - 0x28, 0x33, 0x29, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, - 0x66, 0x2c, 0x20, 0x28, 0x34, 0x29, 0x20, 0x41, 0x54, 0x2f, 0x41, 0x43, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, 0x20, 0x6d, - 0x6f, 0x74, 0x69, 0x66, 0x2e, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, - 0x53, 0x4a, 0x44, 0x42, 0x6f, 0x76, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, - 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, - 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, 0x76, 0x65, 0x72, - 0x68, 0x61, 0x6e, 0x67, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x28, 0x73, 0x6a, 0x64, 0x62, 0x29, 0x20, 0x73, 0x70, 0x6c, 0x69, - 0x63, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x70, 0x6c, - 0x69, 0x63, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x4c, - 0x6d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, - 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, - 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, - 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, - 0x65, 0x64, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x70, 0x6c, - 0x69, 0x63, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x4c, - 0x6d, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x4c, 0x6d, 0x61, 0x74, 0x65, - 0x20, 0x30, 0x2e, 0x36, 0x36, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x61, 0x6c, 0x3e, 0x30, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, - 0x70, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x4d, 0x61, - 0x70, 0x4c, 0x6d, 0x69, 0x6e, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x65, - 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0a, 0x0a, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x50, 0x65, 0x72, - 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x72, 0x65, 0x61, 0x64, - 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x50, 0x65, 0x72, 0x57, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x31, 0x29, 0x20, 0x6e, 0x6f, + 0x6e, 0x2d, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x20, + 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x2c, 0x20, 0x28, 0x32, 0x29, 0x20, + 0x47, 0x54, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x54, + 0x2f, 0x41, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, 0x2c, 0x20, 0x28, + 0x33, 0x29, 0x20, 0x47, 0x43, 0x2f, 0x41, 0x47, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x43, 0x54, 0x2f, 0x47, 0x43, 0x20, 0x6d, 0x6f, 0x74, 0x69, 0x66, + 0x2c, 0x20, 0x28, 0x34, 0x29, 0x20, 0x41, 0x54, 0x2f, 0x41, 0x43, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x47, 0x54, 0x2f, 0x41, 0x54, 0x20, 0x6d, 0x6f, + 0x74, 0x69, 0x66, 0x2e, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, + 0x4a, 0x44, 0x42, 0x6f, 0x76, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x67, 0x4d, + 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, + 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x68, + 0x61, 0x6e, 0x67, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, 0x20, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x20, + 0x28, 0x73, 0x6a, 0x64, 0x62, 0x29, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, + 0x65, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x70, 0x6c, 0x69, + 0x63, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x4c, 0x6d, + 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, + 0x6d, 0x75, 0x6d, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, + 0x64, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x70, 0x6c, 0x69, + 0x63, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x70, 0x4c, 0x6d, + 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x4c, 0x6d, 0x61, 0x74, 0x65, 0x20, + 0x30, 0x2e, 0x36, 0x36, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, + 0x6c, 0x3e, 0x30, 0x3a, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x70, + 0x6c, 0x69, 0x63, 0x65, 0x64, 0x4d, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x70, + 0x4c, 0x6d, 0x69, 0x6e, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x50, 0x65, 0x72, 0x52, + 0x65, 0x61, 0x64, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x77, - 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x50, - 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, + 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x0a, + 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x73, 0x50, 0x65, 0x72, 0x57, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x31, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, + 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x77, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x50, 0x65, + 0x72, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x66, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, - 0x72, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x45, 0x6e, 0x64, 0x73, - 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x6e, - 0x64, 0x73, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x54, + 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x6e, 0x64, + 0x73, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x74, + 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, + 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, - 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, - 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x45, 0x6e, 0x64, 0x54, 0x6f, 0x45, 0x6e, 0x64, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x2d, 0x74, 0x6f, + 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x64, 0x6f, 0x20, + 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, + 0x70, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x35, 0x70, 0x4f, 0x66, + 0x52, 0x65, 0x61, 0x64, 0x31, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, + 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x35, 0x70, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x31, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x65, 0x6e, 0x64, 0x73, 0x3a, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x45, 0x6e, 0x64, 0x54, 0x6f, 0x45, 0x6e, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x2d, 0x74, - 0x6f, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x64, 0x6f, - 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, - 0x69, 0x70, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x35, 0x70, 0x4f, - 0x66, 0x52, 0x65, 0x61, 0x64, 0x31, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x35, - 0x70, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x31, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x3a, 0x20, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x35, 0x70, 0x4f, 0x66, 0x52, 0x65, - 0x61, 0x64, 0x73, 0x31, 0x32, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, - 0x6c, 0x6c, 0x79, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x6f, - 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x35, 0x70, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x32, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x3a, 0x20, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, - 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x50, 0x72, - 0x6f, 0x74, 0x72, 0x75, 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6e, 0x63, 0x6f, 0x72, - 0x64, 0x61, 0x6e, 0x74, 0x50, 0x61, 0x69, 0x72, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x69, 0x2e, 0x65, - 0x2e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x28, 0x65, 0x6e, 0x64, - 0x29, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2b, 0x73, 0x74, - 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x64, 0x6f, - 0x77, 0x6e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x28, 0x65, - 0x6e, 0x64, 0x29, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2d, - 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x31, 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x69, 0x6e, - 0x74, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x6f, - 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x61, 0x73, 0x65, - 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x64, 0x35, 0x70, 0x4f, 0x66, 0x52, 0x65, 0x61, + 0x64, 0x73, 0x31, 0x32, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, + 0x6c, 0x79, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x6e, + 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x35, 0x70, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x32, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x65, 0x6e, 0x64, 0x73, 0x3a, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x50, 0x72, 0x6f, + 0x74, 0x72, 0x75, 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6e, 0x63, 0x6f, 0x72, 0x64, + 0x61, 0x6e, 0x74, 0x50, 0x61, 0x69, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x20, 0x65, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x69, 0x2e, 0x65, 0x2e, + 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x28, 0x65, 0x6e, 0x64, 0x29, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2b, 0x73, 0x74, 0x72, + 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x64, 0x6f, 0x77, + 0x6e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x28, 0x65, 0x6e, + 0x64, 0x29, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2d, 0x73, + 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, - 0x64, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x43, 0x6f, 0x6e, 0x63, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x74, 0x50, 0x61, - 0x69, 0x72, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x7a, 0x65, - 0x72, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, - 0x6e, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x6f, 0x72, 0x64, - 0x61, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x72, - 0x64, 0x61, 0x6e, 0x74, 0x50, 0x61, 0x69, 0x72, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x6e, 0x6f, 0x6e, 0x2d, 0x7a, 0x65, 0x72, 0x6f, 0x20, 0x70, 0x72, 0x6f, - 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x64, - 0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x74, 0x20, 0x70, 0x61, - 0x69, 0x72, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x6f, - 0x66, 0x74, 0x43, 0x6c, 0x69, 0x70, 0x41, 0x74, 0x52, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x73, 0x20, 0x20, 0x20, - 0x20, 0x59, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x70, - 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, - 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, - 0x6f, 0x73, 0x6f, 0x6d, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x59, 0x65, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4e, 0x6f, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x70, 0x72, 0x6f, - 0x68, 0x69, 0x62, 0x69, 0x74, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, - 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, - 0x20, 0x43, 0x75, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x0a, 0x0a, - 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, - 0x6f, 0x6e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x20, - 0x66, 0x6c, 0x75, 0x73, 0x68, 0x20, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, - 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x69, 0x6e, 0x74, + 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x6f, 0x74, + 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, + 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, 0x64, + 0x20, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, - 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, - 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x50, 0x61, 0x69, 0x72, - 0x65, 0x64, 0x2d, 0x45, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, - 0x0a, 0x70, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x4e, 0x62, - 0x61, 0x73, 0x65, 0x73, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x6e, 0x74, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, - 0x75, 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, - 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x20, 0x62, 0x61, 0x73, - 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6d, 0x65, 0x72, 0x67, - 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x70, 0x65, 0x4f, - 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x4d, 0x4d, 0x70, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x2e, 0x30, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, - 0x61, 0x6c, 0x2c, 0x20, 0x3e, 0x3d, 0x30, 0x20, 0x26, 0x20, 0x3c, 0x31, - 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, - 0x6d, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x20, - 0x61, 0x72, 0x65, 0x61, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x57, 0x69, - 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2c, 0x20, 0x41, 0x6e, 0x63, 0x68, 0x6f, - 0x72, 0x73, 0x2c, 0x20, 0x42, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x0a, - 0x0a, 0x77, 0x69, 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, - 0x61, 0x78, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, - 0x20, 0x6c, 0x6f, 0x63, 0x69, 0x20, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, - 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x74, 0x6f, 0x0a, - 0x0a, 0x77, 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x4e, 0x62, 0x69, 0x74, 0x73, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x36, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x3d, - 0x6c, 0x6f, 0x67, 0x32, 0x28, 0x77, 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x29, - 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x42, - 0x69, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, - 0x7a, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, - 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, - 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x77, - 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, - 0x63, 0x63, 0x75, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, - 0x65, 0x67, 0x65, 0x72, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, - 0x6f, 0x66, 0x20, 0x62, 0x69, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x77, 0x69, - 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x74, 0x4e, - 0x62, 0x69, 0x6e, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x39, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x69, 0x6e, - 0x73, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x77, - 0x6f, 0x20, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, - 0x20, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x74, - 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x46, 0x6c, 0x61, 0x6e, 0x6b, 0x4e, 0x62, - 0x69, 0x6e, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6c, - 0x6f, 0x67, 0x32, 0x28, 0x77, 0x69, 0x6e, 0x46, 0x6c, 0x61, 0x6e, 0x6b, - 0x29, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x6e, - 0x20, 0x46, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x6e, 0x6b, 0x69, 0x6e, - 0x67, 0x20, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x43, 0x6f, - 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, - 0x2e, 0x35, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x3e, - 0x3d, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, - 0x63, 0x65, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, - 0x65, 0x64, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, - 0x52, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, - 0x74, 0x68, 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x2e, 0x0a, 0x0a, 0x77, - 0x69, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, - 0x67, 0x65, 0x42, 0x61, 0x73, 0x65, 0x73, 0x4d, 0x69, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, - 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, - 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, - 0x61, 0x73, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, - 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, - 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x20, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, - 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, - 0x68, 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x2e, 0x0a, 0x0a, 0x23, 0x23, - 0x23, 0x20, 0x43, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x41, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x63, 0x68, - 0x69, 0x6d, 0x4f, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, + 0x6f, 0x6e, 0x63, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x74, 0x50, 0x61, 0x69, + 0x72, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x7a, 0x65, 0x72, + 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x6f, 0x72, 0x64, 0x61, + 0x6e, 0x74, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x72, 0x64, + 0x61, 0x6e, 0x74, 0x50, 0x61, 0x69, 0x72, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6e, + 0x6f, 0x6e, 0x2d, 0x7a, 0x65, 0x72, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x74, + 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x64, 0x69, + 0x73, 0x63, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x69, + 0x72, 0x73, 0x0a, 0x0a, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x53, 0x6f, 0x66, + 0x74, 0x43, 0x6c, 0x69, 0x70, 0x41, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x45, 0x6e, 0x64, 0x73, 0x20, 0x20, 0x20, 0x20, + 0x59, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, 0x69, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x70, 0x61, + 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x6f, + 0x73, 0x6f, 0x6d, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x59, 0x65, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x70, 0x72, 0x6f, 0x68, + 0x69, 0x62, 0x69, 0x74, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x43, 0x75, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x0a, 0x0a, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, + 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x3a, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x20, 0x66, + 0x6c, 0x75, 0x73, 0x68, 0x20, 0x61, 0x6d, 0x62, 0x69, 0x67, 0x75, 0x6f, + 0x75, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, - 0x29, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, - 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x43, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x2e, - 0x6f, 0x75, 0x74, 0x2e, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, + 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x69, + 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x72, + 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x65, + 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, - 0x65, 0x53, 0x41, 0x4d, 0x6f, 0x6c, 0x64, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6c, 0x64, 0x20, - 0x53, 0x41, 0x4d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x70, - 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x43, 0x68, 0x69, 0x6d, 0x65, 0x72, - 0x69, 0x63, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x73, 0x61, 0x6d, 0x20, 0x66, - 0x69, 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x69, 0x74, 0x68, - 0x69, 0x6e, 0x42, 0x41, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x69, - 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x20, 0x28, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, - 0x2a, 0x2e, 0x62, 0x61, 0x6d, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, - 0x69, 0x74, 0x68, 0x69, 0x6e, 0x42, 0x41, 0x4d, 0x20, 0x48, 0x61, 0x72, - 0x64, 0x43, 0x6c, 0x69, 0x70, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x28, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x29, 0x20, 0x68, 0x61, 0x72, - 0x64, 0x2d, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x69, - 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x49, 0x47, 0x41, 0x52, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x61, 0x6c, 0x20, 0x63, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, - 0x63, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x69, 0x66, 0x20, + 0x20, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, + 0x74, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x50, 0x61, 0x69, 0x72, 0x65, + 0x64, 0x2d, 0x45, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x0a, + 0x70, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x4e, 0x62, 0x61, + 0x73, 0x65, 0x73, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3e, 0x3d, 0x30, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, + 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, + 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x20, 0x62, 0x61, 0x73, 0x65, + 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, + 0x20, 0x6d, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6d, 0x65, 0x72, 0x67, 0x69, + 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x70, 0x65, 0x4f, 0x76, + 0x65, 0x72, 0x6c, 0x61, 0x70, 0x4d, 0x4d, 0x70, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x2e, 0x30, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, + 0x6c, 0x2c, 0x20, 0x3e, 0x3d, 0x30, 0x20, 0x26, 0x20, 0x3c, 0x31, 0x3a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x20, 0x61, + 0x72, 0x65, 0x61, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x57, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x73, 0x2c, 0x20, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, + 0x73, 0x2c, 0x20, 0x42, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x0a, 0x0a, + 0x77, 0x69, 0x6e, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x4d, 0x75, 0x6c, + 0x74, 0x69, 0x6d, 0x61, 0x70, 0x4e, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, + 0x78, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, + 0x6c, 0x6f, 0x63, 0x69, 0x20, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, + 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x74, 0x6f, 0x0a, 0x0a, + 0x77, 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x4e, 0x62, 0x69, 0x74, 0x73, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x36, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x3d, 0x6c, + 0x6f, 0x67, 0x32, 0x28, 0x77, 0x69, 0x6e, 0x42, 0x69, 0x6e, 0x29, 0x2c, + 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x42, 0x69, + 0x6e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x7a, + 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x6e, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x73, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x77, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6f, 0x63, + 0x63, 0x75, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, + 0x67, 0x65, 0x72, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, + 0x66, 0x20, 0x62, 0x69, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x77, 0x69, 0x6e, + 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x44, 0x69, 0x73, 0x74, 0x4e, 0x62, + 0x69, 0x6e, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x39, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, + 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x61, 0x78, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x69, 0x6e, 0x73, + 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x77, 0x6f, + 0x20, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, + 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x0a, + 0x0a, 0x77, 0x69, 0x6e, 0x46, 0x6c, 0x61, 0x6e, 0x6b, 0x4e, 0x62, 0x69, + 0x6e, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x6c, 0x6f, + 0x67, 0x32, 0x28, 0x77, 0x69, 0x6e, 0x46, 0x6c, 0x61, 0x6e, 0x6b, 0x29, + 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x20, + 0x46, 0x6c, 0x61, 0x6e, 0x6b, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x69, + 0x67, 0x68, 0x74, 0x20, 0x66, 0x6c, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x67, + 0x20, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x0a, 0x0a, 0x77, 0x69, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x76, + 0x65, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, + 0x65, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, + 0x35, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x3e, 0x3d, + 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, + 0x65, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x65, + 0x64, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, + 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, + 0x68, 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x2e, 0x0a, 0x0a, 0x77, 0x69, + 0x6e, 0x52, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x67, + 0x65, 0x42, 0x61, 0x73, 0x65, 0x73, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, + 0x3e, 0x30, 0x3a, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, + 0x73, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, + 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x73, + 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x20, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, 0x6c, + 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x2e, 0x0a, 0x0a, 0x23, 0x23, 0x23, + 0x20, 0x43, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x41, 0x6c, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x63, 0x68, 0x69, + 0x6d, 0x4f, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, + 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x68, + 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x43, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x2e, 0x6f, + 0x75, 0x74, 0x2e, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x53, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, + 0x53, 0x41, 0x4d, 0x6f, 0x6c, 0x64, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x53, + 0x41, 0x4d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x70, 0x61, + 0x72, 0x61, 0x74, 0x65, 0x20, 0x43, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, + 0x63, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x73, 0x61, 0x6d, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x69, 0x74, 0x68, 0x69, + 0x6e, 0x42, 0x41, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x69, 0x6e, + 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x20, 0x28, 0x41, 0x6c, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x2a, + 0x2e, 0x62, 0x61, 0x6d, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x42, 0x41, 0x4d, 0x20, 0x48, 0x61, 0x72, 0x64, + 0x43, 0x6c, 0x69, 0x70, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x28, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x29, 0x20, 0x68, 0x61, 0x72, 0x64, + 0x2d, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x49, 0x47, 0x41, 0x52, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x6c, 0x20, 0x63, 0x68, 0x69, 0x6d, 0x65, 0x72, 0x69, 0x63, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, + 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, @@ -2796,7 +3398,7 @@ unsigned char parametersDefault[] = { 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x68, 0x61, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, - 0x65, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x0a, 0x0a, 0x63, 0x68, 0x69, 0x6d, 0x4f, 0x75, 0x74, 0x4a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, @@ -2820,383 +3422,1117 @@ unsigned char parametersDefault[] = { 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x20, 0x74, 0x6f, 0x74, - 0x61, 0x6c, 0x2c, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2c, 0x20, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x51, - 0x75, 0x61, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x4d, 0x6f, - 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, - 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x71, - 0x75, 0x61, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x0a, + 0x61, 0x6c, 0x2c, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x2f, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, + 0x71, 0x75, 0x61, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x53, - 0x41, 0x4d, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x20, 0x53, 0x41, 0x4d, 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x61, 0x6c, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, - 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, 0x65, 0x70, - 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, - 0x70, 0x65, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x0a, 0x0a, 0x71, 0x75, - 0x61, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x6f, 0x6d, 0x65, 0x42, 0x41, 0x4d, 0x63, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x2d, 0x32, 0x20, 0x74, 0x6f, 0x20, 0x31, - 0x30, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x6f, 0x6d, 0x65, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x32, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x6e, 0x65, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x28, 0x36, 0x3f, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x53, 0x41, 0x4d, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x53, 0x41, 0x4d, + 0x2f, 0x42, 0x41, 0x4d, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, + 0x6f, 0x20, 0x61, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, + 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, 0x67, + 0x65, 0x6e, 0x65, 0x0a, 0x0a, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x42, + 0x41, 0x4d, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, + 0x2d, 0x32, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x30, 0x20, 0x20, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x20, + 0x42, 0x41, 0x4d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2d, 0x32, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, + 0x20, 0x42, 0x41, 0x4d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, + 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x36, 0x3f, 0x29, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x20, 0x2e, 0x2e, 0x2e, + 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x30, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x78, - 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, - 0x42, 0x61, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x6e, - 0x64, 0x65, 0x6c, 0x53, 0x6f, 0x66, 0x74, 0x63, 0x6c, 0x69, 0x70, 0x53, - 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x6f, - 0x68, 0x69, 0x62, 0x69, 0x74, 0x20, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, - 0x73, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x64, - 0x65, 0x6c, 0x53, 0x6f, 0x66, 0x74, 0x63, 0x6c, 0x69, 0x70, 0x53, 0x69, - 0x6e, 0x67, 0x6c, 0x65, 0x65, 0x6e, 0x64, 0x20, 0x20, 0x2e, 0x2e, 0x2e, - 0x20, 0x70, 0x72, 0x6f, 0x68, 0x69, 0x62, 0x69, 0x74, 0x20, 0x69, 0x6e, - 0x64, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x63, - 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x61, - 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x2d, 0x20, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, - 0x69, 0x74, 0x68, 0x20, 0x52, 0x53, 0x45, 0x4d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x65, 0x6e, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x70, 0x72, 0x6f, 0x68, 0x69, 0x62, 0x69, - 0x74, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x65, 0x6e, 0x64, - 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, - 0x0a, 0x23, 0x23, 0x23, 0x20, 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x0a, 0x74, 0x77, 0x6f, 0x70, - 0x61, 0x73, 0x73, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, + 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x0a, + 0x0a, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x6d, 0x65, 0x42, 0x61, 0x6e, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x64, 0x65, 0x6c, 0x53, 0x6f, + 0x66, 0x74, 0x63, 0x6c, 0x69, 0x70, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x3a, 0x20, 0x70, 0x72, 0x6f, 0x68, 0x69, 0x62, 0x69, 0x74, + 0x20, 0x76, 0x61, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x49, 0x6e, 0x64, 0x65, 0x6c, 0x53, 0x6f, 0x66, + 0x74, 0x63, 0x6c, 0x69, 0x70, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x65, + 0x6e, 0x64, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x70, 0x72, 0x6f, 0x68, + 0x69, 0x62, 0x69, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x6c, 0x73, 0x2c, + 0x20, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x74, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x52, + 0x53, 0x45, 0x4d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x65, 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x70, 0x72, 0x6f, 0x68, 0x69, 0x62, 0x69, 0x74, 0x20, 0x73, 0x69, 0x6e, + 0x67, 0x6c, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, + 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x0a, 0x74, 0x77, 0x6f, 0x70, 0x61, 0x73, 0x73, 0x4d, 0x6f, + 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, + 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, - 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x6f, 0x64, 0x65, - 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x31, 0x2d, + 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x31, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, + 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x42, 0x61, 0x73, 0x69, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x73, 0x69, 0x63, 0x20, 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x31, + 0x73, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6a, 0x75, 0x6e, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, + 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, + 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, + 0x79, 0x0a, 0x0a, 0x74, 0x77, 0x6f, 0x70, 0x61, 0x73, 0x73, 0x31, 0x72, + 0x65, 0x61, 0x64, 0x73, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, 0x73, 0x74, 0x20, 0x73, 0x74, + 0x65, 0x70, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x20, 0x76, 0x65, 0x72, 0x79, + 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x20, 0x28, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x70, + 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x69, + 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, + 0x73, 0x74, 0x65, 0x70, 0x2e, 0x0a, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, + 0x57, 0x41, 0x53, 0x50, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x73, 0x0a, 0x77, 0x61, 0x73, 0x70, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, + 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x65, + 0x2d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x6f, 0x75, + 0x74, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x2e, 0x20, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x2d, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x6d, 0x61, + 0x70, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x79, 0x20, 0x42, + 0x72, 0x79, 0x63, 0x65, 0x20, 0x76, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x20, + 0x47, 0x65, 0x69, 0x6a, 0x6e, 0x2c, 0x20, 0x47, 0x72, 0x61, 0x68, 0x61, + 0x6d, 0x20, 0x4d, 0x63, 0x56, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x2c, 0x20, + 0x59, 0x6f, 0x61, 0x76, 0x20, 0x47, 0x69, 0x6c, 0x61, 0x64, 0x20, 0x26, + 0x20, 0x4a, 0x6f, 0x6e, 0x61, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x4b, 0x20, + 0x50, 0x72, 0x69, 0x74, 0x63, 0x68, 0x61, 0x72, 0x64, 0x2e, 0x20, 0x50, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x63, 0x69, 0x74, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, + 0x57, 0x41, 0x53, 0x50, 0x20, 0x70, 0x61, 0x70, 0x65, 0x72, 0x3a, 0x20, + 0x4e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x73, 0x20, 0x31, 0x32, 0x2c, 0x20, 0x31, 0x30, 0x36, 0x31, 0xe2, + 0x80, 0x93, 0x31, 0x30, 0x36, 0x33, 0x20, 0x28, 0x32, 0x30, 0x31, 0x35, + 0x29, 0x2c, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x73, 0x2f, 0x6e, + 0x6d, 0x65, 0x74, 0x68, 0x2e, 0x33, 0x35, 0x38, 0x32, 0x20, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, 0x74, 0x61, 0x67, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x64, 0x64, 0x20, + 0x57, 0x41, 0x53, 0x50, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x73, + 0x73, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x20, 0x53, 0x54, + 0x41, 0x52, 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x28, 0x73, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x52, 0x4e, 0x41, 0x2d, + 0x73, 0x65, 0x71, 0x29, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x73, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x54, 0x79, 0x70, 0x65, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, + 0x73, 0x29, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x63, 0x65, 0x6c, 0x6c, 0x20, + 0x52, 0x4e, 0x41, 0x2d, 0x73, 0x65, 0x71, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x43, 0x42, 0x5f, 0x55, 0x4d, 0x49, 0x5f, 0x53, 0x69, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x28, 0x61, 0x2e, 0x6b, + 0x2e, 0x61, 0x2e, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x6c, 0x65, 0x74, 0x29, + 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x20, 0x42, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x78, + 0x65, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x69, 0x6e, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x32, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, + 0x20, 0x44, 0x72, 0x6f, 0x70, 0x2d, 0x73, 0x65, 0x71, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x31, 0x30, 0x58, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x69, + 0x75, 0x6d, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x42, 0x5f, 0x55, + 0x4d, 0x49, 0x5f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, + 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x20, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, + 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, + 0x67, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, + 0x65, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x78, + 0x65, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, + 0x72, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, + 0x66, 0x20, 0x66, 0x69, 0x78, 0x65, 0x64, 0x20, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x32, 0x20, + 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x28, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x69, + 0x6e, 0x44, 0x72, 0x6f, 0x70, 0x2c, 0x20, 0x64, 0x64, 0x53, 0x65, 0x71, + 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x42, 0x61, 0x73, 0x69, 0x63, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x73, - 0x69, 0x63, 0x20, 0x32, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x61, 0x6c, 0x6c, 0x20, 0x31, 0x73, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, - 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, - 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x6c, 0x79, 0x0a, 0x0a, 0x74, 0x77, 0x6f, 0x70, - 0x61, 0x73, 0x73, 0x31, 0x72, 0x65, 0x61, 0x64, 0x73, 0x4e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x31, - 0x73, 0x74, 0x20, 0x73, 0x74, 0x65, 0x70, 0x2e, 0x20, 0x55, 0x73, 0x65, - 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x28, 0x6f, 0x72, 0x20, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x2d, 0x31, 0x29, 0x20, 0x74, - 0x6f, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x20, 0x73, 0x74, 0x65, 0x70, 0x2e, 0x0a, 0x0a, - 0x0a, 0x23, 0x23, 0x23, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x0a, 0x77, 0x61, 0x73, - 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x61, - 0x6c, 0x6c, 0x65, 0x6c, 0x65, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, - 0x69, 0x63, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x72, 0x65, 0x2d, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x57, 0x41, 0x53, - 0x50, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, - 0x62, 0x79, 0x20, 0x42, 0x72, 0x79, 0x63, 0x65, 0x20, 0x76, 0x61, 0x6e, - 0x20, 0x64, 0x65, 0x20, 0x47, 0x65, 0x69, 0x6a, 0x6e, 0x2c, 0x20, 0x47, - 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x4d, 0x63, 0x56, 0x69, 0x63, 0x6b, - 0x65, 0x72, 0x2c, 0x20, 0x59, 0x6f, 0x61, 0x76, 0x20, 0x47, 0x69, 0x6c, - 0x61, 0x64, 0x20, 0x26, 0x20, 0x4a, 0x6f, 0x6e, 0x61, 0x74, 0x68, 0x61, - 0x6e, 0x20, 0x4b, 0x20, 0x50, 0x72, 0x69, 0x74, 0x63, 0x68, 0x61, 0x72, - 0x64, 0x2e, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x63, 0x69, - 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x6c, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x70, 0x61, 0x70, - 0x65, 0x72, 0x3a, 0x20, 0x4e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x20, 0x31, 0x32, 0x2c, 0x20, 0x31, - 0x30, 0x36, 0x31, 0xe2, 0x80, 0x93, 0x31, 0x30, 0x36, 0x33, 0x20, 0x28, - 0x32, 0x30, 0x31, 0x35, 0x29, 0x2c, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, - 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, - 0x65, 0x73, 0x2f, 0x6e, 0x6d, 0x65, 0x74, 0x68, 0x2e, 0x33, 0x35, 0x38, - 0x32, 0x20, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x41, 0x4d, 0x74, - 0x61, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x61, 0x64, 0x64, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x74, 0x61, 0x67, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x57, 0x41, 0x53, 0x50, 0x20, 0x66, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x0a, 0x23, 0x23, - 0x23, 0x20, 0x53, 0x54, 0x41, 0x52, 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x28, - 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, - 0x52, 0x4e, 0x41, 0x2d, 0x73, 0x65, 0x71, 0x29, 0x20, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, - 0x54, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x42, 0x5f, 0x73, 0x61, + 0x6d, 0x54, 0x61, 0x67, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x43, 0x65, + 0x6c, 0x6c, 0x20, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, + 0x73, 0x20, 0x43, 0x52, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, + 0x43, 0x42, 0x20, 0x53, 0x41, 0x6d, 0x20, 0x74, 0x61, 0x67, 0x2e, 0x20, + 0x4e, 0x6f, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x49, 0x6e, 0x20, 0x63, 0x44, 0x4e, 0x41, 0x5f, + 0x72, 0x65, 0x61, 0x64, 0x31, 0x20, 0x5b, 0x63, 0x44, 0x4e, 0x41, 0x5f, + 0x72, 0x65, 0x61, 0x64, 0x32, 0x20, 0x69, 0x66, 0x20, 0x70, 0x61, 0x69, + 0x72, 0x65, 0x64, 0x2d, 0x65, 0x6e, 0x64, 0x5d, 0x20, 0x43, 0x65, 0x6c, + 0x6c, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x61, + 0x64, 0x20, 0x2e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, + 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x42, 0x41, 0x4d, 0x20, 0x55, 0x6e, 0x73, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x20, 0x5b, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72, 0x20, 0x53, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x42, 0x79, 0x43, 0x6f, 0x6f, 0x72, 0x64, + 0x69, 0x6e, 0x61, 0x74, 0x65, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x6f, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x63, - 0x65, 0x6c, 0x6c, 0x20, 0x52, 0x4e, 0x41, 0x2d, 0x73, 0x65, 0x71, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x44, 0x72, 0x6f, 0x70, 0x6c, 0x65, 0x74, 0x20, - 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x65, - 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, - 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x62, - 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x32, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x44, 0x72, - 0x6f, 0x70, 0x2d, 0x73, 0x65, 0x71, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x31, - 0x30, 0x58, 0x20, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x0a, - 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x6c, 0x69, 0x73, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, - 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, - 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, - 0x6f, 0x43, 0x42, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, - 0x3a, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, - 0x64, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x62, 0x61, 0x73, - 0x65, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x6c, 0x65, 0x6e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x36, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x63, 0x65, 0x6c, - 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x55, 0x4d, - 0x49, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x37, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, + 0x6d, 0x61, 0x72, 0x74, 0x53, 0x65, 0x71, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x53, 0x6d, 0x61, 0x72, 0x74, + 0x2d, 0x73, 0x65, 0x71, 0x3a, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x63, + 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x65, 0x70, + 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x46, 0x41, 0x53, 0x54, 0x51, 0x20, + 0x28, 0x70, 0x61, 0x69, 0x72, 0x65, 0x64, 0x2d, 0x20, 0x6f, 0x72, 0x20, + 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x29, 0x2c, + 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, 0x72, + 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x2c, 0x20, 0x6e, 0x6f, 0x20, 0x55, 0x4d, 0x49, 0x20, + 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2c, 0x20, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x64, 0x65, + 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, + 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, + 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x20, + 0x28, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x2d, 0x63, 0x6c, + 0x69, 0x70, 0x70, 0x65, 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x29, + 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x77, 0x68, 0x69, 0x74, + 0x65, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x28, 0x73, 0x29, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x28, 0x73, 0x29, + 0x20, 0x6f, 0x66, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x72, + 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, + 0x2d, 0x2d, 0x73, 0x6f, 0x6c, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x20, 0x43, + 0x42, 0x5f, 0x55, 0x4d, 0x49, 0x5f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x78, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x6d, 0x6f, 0x72, + 0x65, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, + 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, + 0x69, 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x65, 0x6c, + 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x0a, + 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, + 0x62, 0x61, 0x73, 0x65, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, + 0x6c, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x36, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, - 0x55, 0x4d, 0x49, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x62, 0x61, - 0x73, 0x65, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x55, 0x4d, 0x49, 0x6c, - 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x55, 0x4d, - 0x49, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0a, 0x0a, 0x73, 0x6f, - 0x6c, 0x6f, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x61, - 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3a, - 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, + 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, + 0x6f, 0x55, 0x4d, 0x49, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x31, 0x37, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, + 0x30, 0x3a, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x20, 0x62, 0x61, 0x73, 0x65, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x55, + 0x4d, 0x49, 0x6c, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, + 0x20, 0x55, 0x4d, 0x49, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0a, + 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x61, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, + 0x6e, 0x74, 0x3a, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, + 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, + 0x20, 0x74, 0x6f, 0x20, 0x73, 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x73, + 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x6c, 0x65, 0x6e, 0x2b, 0x73, 0x6f, 0x6c, + 0x6f, 0x55, 0x4d, 0x49, 0x6c, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x64, 0x6f, 0x20, + 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x0a, 0x0a, 0x73, + 0x6f, 0x6c, 0x6f, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, + 0x74, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x28, 0x43, 0x42, 0x2b, 0x55, 0x4d, + 0x49, 0x29, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, + 0x65, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x73, + 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x68, 0x6f, 0x75, + 0x6c, 0x64, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x62, 0x65, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2d, 0x2d, + 0x72, 0x65, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x49, 0x6e, 0x20, + 0x6c, 0x69, 0x73, 0x74, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, + 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, + 0x64, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x32, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x72, 0x63, + 0x6f, 0x64, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, + 0x66, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x32, 0x0a, 0x0a, 0x73, 0x6f, + 0x6c, 0x6f, 0x43, 0x42, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x73, 0x28, 0x73, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x65, 0x6c, 0x6c, + 0x20, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x28, 0x73, 0x29, 0x20, + 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, + 0x64, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x73, 0x6f, 0x6c, 0x6f, 0x54, 0x79, 0x70, + 0x65, 0x20, 0x43, 0x42, 0x5f, 0x55, 0x4d, 0x49, 0x5f, 0x43, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x78, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, + 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, + 0x20, 0x6f, 0x6e, 0x20, 0x52, 0x65, 0x61, 0x64, 0x32, 0x2e, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, + 0x64, 0x65, 0x3a, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x41, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x41, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x28, 0x65, 0x6e, 0x64, 0x29, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, + 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x20, 0x42, 0x61, 0x73, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x42, 0x3a, + 0x20, 0x30, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x3b, 0x20, 0x31, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, + 0x65, 0x6e, 0x64, 0x3b, 0x20, 0x32, 0x3a, 0x20, 0x61, 0x64, 0x61, 0x70, + 0x74, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3b, 0x20, 0x33, + 0x3a, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x65, 0x6e, + 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x28, + 0x65, 0x6e, 0x64, 0x29, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x30, 0x2d, 0x62, 0x61, + 0x73, 0x65, 0x64, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x43, 0x42, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x28, 0x65, 0x6e, + 0x64, 0x29, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x72, 0x65, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, + 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x20, 0x42, 0x61, 0x73, 0x65, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, + 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, + 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, + 0x79, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x20, 0x69, 0x6e, + 0x44, 0x72, 0x6f, 0x70, 0x20, 0x28, 0x5a, 0x69, 0x6c, 0x69, 0x6f, 0x6e, + 0x69, 0x73, 0x20, 0x65, 0x74, 0x20, 0x61, 0x6c, 0x2c, 0x20, 0x4e, 0x61, + 0x74, 0x2e, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, + 0x2c, 0x20, 0x32, 0x30, 0x31, 0x37, 0x29, 0x3a, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2d, 0x2d, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x30, 0x5f, 0x30, 0x5f, 0x32, + 0x5f, 0x2d, 0x31, 0x20, 0x20, 0x33, 0x5f, 0x31, 0x5f, 0x33, 0x5f, 0x38, + 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x55, 0x4d, 0x49, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x20, 0x74, 0x6f, - 0x20, 0x73, 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x6f, 0x6c, 0x6f, - 0x43, 0x42, 0x6c, 0x65, 0x6e, 0x2b, 0x73, 0x6f, 0x6c, 0x6f, 0x55, 0x4d, - 0x49, 0x6c, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x66, 0x69, - 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x53, - 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, - 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, - 0x64, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x6c, 0x69, 0x62, 0x72, - 0x61, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x65, 0x61, 0x64, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, + 0x20, 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x3a, 0x20, 0x69, 0x6e, 0x44, 0x72, 0x6f, 0x70, 0x20, + 0x28, 0x5a, 0x69, 0x6c, 0x69, 0x6f, 0x6e, 0x69, 0x73, 0x20, 0x65, 0x74, + 0x20, 0x61, 0x6c, 0x2c, 0x20, 0x4e, 0x61, 0x74, 0x2e, 0x20, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x2c, 0x20, 0x32, 0x30, 0x31, + 0x37, 0x29, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x6f, + 0x6c, 0x6f, 0x43, 0x42, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x20, 0x33, 0x5f, 0x39, 0x5f, 0x33, 0x5f, 0x31, 0x34, 0x0a, 0x0a, + 0x73, 0x6f, 0x6c, 0x6f, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x53, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x64, + 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, + 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2e, 0x20, 0x4f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x64, 0x61, 0x70, + 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, + 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x41, 0x64, 0x61, 0x70, 0x74, 0x65, + 0x72, 0x4d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x4e, + 0x6d, 0x61, 0x78, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x69, 0x6e, 0x74, 0x3e, 0x30, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x6e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x20, 0x69, 0x6e, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x20, + 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x0a, 0x73, + 0x6f, 0x6c, 0x6f, 0x43, 0x42, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x57, 0x4c, + 0x74, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, - 0x6e, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, - 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, + 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x20, 0x42, + 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x57, 0x68, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, - 0x64, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6d, - 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, - 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x52, 0x4e, 0x41, 0x20, 0x6d, 0x6f, - 0x6c, 0x65, 0x63, 0x75, 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x78, 0x61, 0x63, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, - 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, - 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x73, 0x74, 0x72, 0x61, - 0x6e, 0x64, 0x20, 0x6f, 0x70, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x6c, 0x20, 0x52, 0x4e, 0x41, 0x20, 0x6d, 0x6f, 0x6c, 0x65, - 0x63, 0x75, 0x6c, 0x65, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, - 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, - 0x69, 0x63, 0x20, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, - 0x20, 0x70, 0x65, 0x72, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x20, 0x42, 0x61, - 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x65, 0x78, + 0x61, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x47, 0x65, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x65, - 0x73, 0x3a, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x6d, 0x61, 0x74, - 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x4d, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x4a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, - 0x70, 0x6c, 0x69, 0x63, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x4a, 0x2e, 0x6f, 0x75, 0x74, 0x2e, - 0x74, 0x61, 0x62, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, - 0x46, 0x75, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, - 0x65, 0x73, 0x3a, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x61, 0x6c, - 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, - 0x6c, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x67, 0x65, 0x6e, 0x65, - 0x73, 0x27, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x73, 0x6f, - 0x6c, 0x6f, 0x55, 0x4d, 0x49, 0x64, 0x65, 0x64, 0x75, 0x70, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x41, 0x6c, 0x6c, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, + 0x69, 0x73, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x31, 0x20, 0x6d, + 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x62, 0x61, + 0x73, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x20, + 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x43, 0x42, 0x73, 0x20, + 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x61, 0x76, 0x65, + 0x20, 0x61, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, + 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x65, 0x78, 0x61, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x2e, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, + 0x65, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x69, 0x6e, + 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x31, 0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x64, 0x20, 0x62, 0x61, 0x73, 0x65, 0x20, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2c, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x65, + 0x72, 0x69, 0x6f, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x63, 0x68, 0x6f, 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x20, 0x43, 0x42, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, + 0x20, 0x74, 0x6f, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x74, 0x20, + 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x78, 0x61, 0x63, + 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x20, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x65, 0x73, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x72, 0x20, 0x32, 0x2e, 0x32, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x31, 0x4d, 0x4d, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x70, 0x73, + 0x65, 0x75, 0x64, 0x6f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x31, 0x4d, 0x4d, 0x5f, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x70, + 0x73, 0x65, 0x75, 0x64, 0x6f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, + 0x6f, 0x66, 0x20, 0x31, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, + 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x68, + 0x69, 0x74, 0x65, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x62, 0x61, 0x72, 0x63, + 0x6f, 0x64, 0x65, 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, + 0x4d, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x4e, 0x62, 0x61, 0x73, + 0x65, 0x5f, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x73, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x61, + 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x5f, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x57, + 0x4c, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x43, 0x42, 0x73, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x4e, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2e, 0x20, 0x54, + 0x68, 0x69, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x72, 0x20, 0x3e, 0x3d, 0x20, 0x33, 0x2e, 0x30, 0x2e, 0x30, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x69, + 0x6f, 0x5f, 0x45, 0x44, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x75, + 0x70, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x64, 0x69, 0x74, 0x20, 0x64, 0x69, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x33, 0x20, + 0x66, 0x70, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, + 0x2e, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x2b, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x6e, 0x73, + 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, + 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x2d, 0x2d, 0x73, 0x6f, 0x6c, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x20, 0x43, + 0x42, 0x5f, 0x55, 0x4d, 0x49, 0x5f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x78, 0x2e, 0x20, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x70, + 0x61, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x62, 0x61, 0x72, 0x63, + 0x64, 0x6f, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, + 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x20, 0x53, 0x69, + 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x42, 0x69, 0x6f, 0x20, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x2d, + 0x73, 0x65, 0x71, 0x20, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65, + 0x2e, 0x20, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x49, 0x6e, 0x70, 0x75, + 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, 0x74, 0x72, 0x42, 0x61, 0x72, 0x63, + 0x6f, 0x64, 0x65, 0x53, 0x65, 0x71, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x4d, - 0x49, 0x20, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, - 0x69, 0x6e, 0x67, 0x29, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, - 0x68, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x28, 0x2d, 0x2d, 0x72, 0x65, 0x61, 0x64, 0x73, 0x46, + 0x69, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, + 0x53, 0x45, 0x2f, 0x50, 0x45, 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x73, + 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x70, + 0x72, 0x6f, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x29, + 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x41, - 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x55, - 0x4d, 0x49, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x31, 0x20, 0x6d, - 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x64, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, - 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, - 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x28, 0x69, 0x2e, - 0x65, 0x2e, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6f, - 0x6e, 0x63, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x31, 0x30, 0x58, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, 0x73, 0x6f, + 0x6c, 0x6f, 0x20, 0x42, 0x41, 0x4d, 0x73, 0x2c, 0x20, 0x75, 0x73, 0x65, + 0x20, 0x2d, 0x2d, 0x73, 0x6f, 0x6c, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x53, 0x41, 0x4d, 0x61, 0x74, 0x74, 0x72, 0x42, 0x61, 0x72, 0x63, 0x6f, + 0x64, 0x65, 0x53, 0x65, 0x71, 0x20, 0x43, 0x52, 0x20, 0x55, 0x52, 0x20, + 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, - 0x5f, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x6f, 0x6c, - 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x20, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x55, 0x4d, 0x49, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x73, - 0x20, 0x62, 0x79, 0x20, 0x53, 0x6d, 0x69, 0x74, 0x68, 0x2c, 0x20, 0x48, - 0x65, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x75, 0x64, - 0x62, 0x65, 0x72, 0x79, 0x20, 0x28, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, - 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x32, 0x30, - 0x31, 0x37, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, + 0x6e, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x54, + 0x41, 0x52, 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x53, + 0x41, 0x4d, 0x2e, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x73, 0x6f, + 0x6c, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, 0x74, + 0x74, 0x72, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x51, 0x75, 0x61, + 0x6c, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x65, + 0x6e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, + 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, + 0x20, 0x53, 0x41, 0x4d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x2d, + 0x2d, 0x72, 0x65, 0x61, 0x64, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x79, + 0x70, 0x65, 0x20, 0x53, 0x41, 0x4d, 0x20, 0x53, 0x45, 0x2f, 0x50, 0x45, + 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x53, 0x41, 0x4d, + 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x20, + 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, + 0x63, 0x6f, 0x64, 0x65, 0x20, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x20, 0x28, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x29, 0x2e, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x31, 0x30, 0x58, 0x20, + 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x6f, + 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x42, + 0x41, 0x4d, 0x73, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x20, 0x2d, 0x2d, 0x73, + 0x6f, 0x6c, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x41, 0x4d, 0x61, + 0x74, 0x74, 0x72, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x51, 0x75, + 0x61, 0x6c, 0x20, 0x43, 0x59, 0x20, 0x55, 0x59, 0x20, 0x2e, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x49, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, + 0x27, 0x2d, 0x27, 0x20, 0x28, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x29, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x20, 0x27, 0x48, 0x27, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, + 0x62, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, + 0x2e, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x53, 0x74, 0x72, 0x61, 0x6e, + 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x3a, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x6e, + 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6f, 0x6c, 0x6f, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, + 0x73, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x73, 0x74, 0x72, + 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, + 0x6f, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x73, 0x74, + 0x72, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, + 0x6c, 0x20, 0x52, 0x4e, 0x41, 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x63, 0x75, + 0x6c, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x76, 0x65, 0x72, + 0x73, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6f, + 0x70, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, + 0x52, 0x4e, 0x41, 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x63, 0x75, 0x6c, 0x65, + 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, + 0x3a, 0x20, 0x67, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x20, 0x66, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, + 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x4d, 0x49, + 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20, + 0x43, 0x65, 0x6c, 0x6c, 0x20, 0x42, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, + 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x3a, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x63, 0x65, + 0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, + 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, + 0x53, 0x4a, 0x2e, 0x6f, 0x75, 0x74, 0x2e, 0x74, 0x61, 0x62, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, + 0x75, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x28, 0x70, 0x72, + 0x65, 0x2d, 0x6d, 0x52, 0x4e, 0x41, 0x29, 0x3a, 0x20, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, + 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x20, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x27, 0x20, 0x65, 0x78, 0x6f, 0x6e, + 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, + 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x46, 0x75, + 0x6c, 0x6c, 0x5f, 0x45, 0x78, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x49, + 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, + 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x28, 0x70, 0x72, 0x65, + 0x2d, 0x6d, 0x52, 0x4e, 0x41, 0x29, 0x3a, 0x20, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, + 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, + 0x67, 0x65, 0x6e, 0x65, 0x73, 0x27, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x73, + 0x3a, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, + 0x20, 0x31, 0x30, 0x30, 0x25, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, + 0x70, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x46, 0x75, 0x6c, + 0x6c, 0x5f, 0x45, 0x78, 0x35, 0x30, 0x70, 0x41, 0x53, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x75, 0x6c, + 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x28, 0x70, 0x72, 0x65, 0x2d, + 0x52, 0x4e, 0x41, 0x29, 0x3a, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, + 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x6f, 0x76, + 0x65, 0x72, 0x6c, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x67, 0x65, + 0x6e, 0x65, 0x73, 0x27, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x73, 0x3a, 0x20, + 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x20, 0x3e, + 0x35, 0x30, 0x25, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x73, 0x2e, 0x20, + 0x44, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, + 0x31, 0x30, 0x30, 0x25, 0x20, 0x65, 0x78, 0x6f, 0x6e, 0x69, 0x63, 0x20, + 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x61, 0x6e, 0x74, 0x69, 0x73, 0x65, 0x6e, 0x73, 0x65, + 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, + 0x0a, 0x23, 0x23, 0x23, 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x44, + 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x62, + 0x65, 0x67, 0x69, 0x6e, 0x20, 0x3a, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x2d, 0x20, 0x64, + 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x33, 0x70, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x71, 0x75, + 0x61, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x33, 0x27, 0x20, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x0a, 0x23, 0x23, 0x23, 0x23, + 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x73, + 0x6f, 0x6c, 0x6f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x4d, 0x61, 0x70, 0x70, + 0x65, 0x72, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, + 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x61, + 0x64, 0x73, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, + 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x67, + 0x65, 0x6e, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x71, + 0x75, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x70, + 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x67, + 0x65, 0x6e, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x6e, 0x69, + 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x6c, 0x79, 0x20, 0x64, 0x69, + 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x2d, 0x67, 0x65, 0x6e, 0x69, 0x63, 0x20, 0x55, 0x4d, 0x49, + 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, + 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x73, 0x63, 0x75, + 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, 0x69, + 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x55, 0x4d, 0x49, + 0x73, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x6e, 0x69, 0x71, + 0x75, 0x65, 0x2b, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x28, 0x7e, 0x20, 0x66, 0x69, 0x72, + 0x73, 0x74, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x45, 0x4d, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x72, 0x6f, 0x70, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x20, 0x55, 0x4d, 0x49, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x6f, + 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x74, 0x6f, + 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x6d, 0x61, 0x70, 0x70, + 0x65, 0x72, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x70, 0x72, 0x65, 0x73, + 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x69, + 0x66, 0x6f, 0x72, 0x6d, 0x6c, 0x79, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, + 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x4d, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x2d, 0x67, 0x65, 0x6e, 0x65, 0x20, 0x55, 0x4d, 0x49, + 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x64, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, + 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x0a, 0x0a, + 0x73, 0x6f, 0x6c, 0x6f, 0x55, 0x4d, 0x49, 0x64, 0x65, 0x64, 0x75, 0x70, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x41, 0x6c, 0x6c, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, + 0x29, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x55, 0x4d, 0x49, 0x20, 0x64, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6c, 0x61, + 0x70, 0x73, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, + 0x69, 0x74, 0x68, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, - 0x5f, 0x4e, 0x6f, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x55, - 0x4d, 0x49, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x31, 0x20, 0x6d, - 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x64, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, - 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x28, 0x69, 0x2e, - 0x65, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x65, 0x64, 0x29, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x4f, 0x75, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x6f, 0x6c, - 0x6f, 0x2e, 0x6f, 0x75, 0x74, 0x2f, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x73, - 0x2e, 0x74, 0x73, 0x76, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, - 0x73, 0x2e, 0x74, 0x73, 0x76, 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x2e, 0x6d, 0x74, 0x78, 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x53, - 0x4a, 0x2e, 0x6d, 0x74, 0x78, 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x47, 0x65, 0x6e, 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x2e, 0x6d, 0x74, 0x78, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, - 0x73, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, - 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x0a, + 0x5f, 0x41, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x55, 0x4d, 0x49, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x31, 0x20, 0x6d, 0x69, 0x73, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6f, + 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6c, + 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x20, 0x28, 0x69, 0x2e, 0x65, 0x2e, + 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x63, + 0x65, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, + 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, + 0x55, 0x4d, 0x49, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x20, 0x20, 0x20, 0x20, + 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x22, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x55, 0x4d, + 0x49, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x20, 0x62, 0x79, 0x20, 0x53, + 0x6d, 0x69, 0x74, 0x68, 0x2c, 0x20, 0x48, 0x65, 0x67, 0x65, 0x72, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x53, 0x75, 0x64, 0x62, 0x65, 0x72, 0x79, 0x20, + 0x28, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x32, 0x30, 0x31, 0x37, 0x29, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x44, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, + 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x31, 0x4d, 0x4d, 0x5f, + 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, + 0x55, 0x4d, 0x49, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2c, 0x20, 0x62, 0x75, + 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x72, + 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, + 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x55, 0x4d, 0x49, + 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x45, 0x78, 0x61, 0x63, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x31, 0x73, 0x74, 0x20, 0x77, 0x6f, 0x72, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x66, 0x69, 0x6c, 0x65, - 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, + 0x6c, 0x79, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, + 0x55, 0x4d, 0x49, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6c, + 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x67, 0x65, 0x6e, - 0x65, 0x20, 0x49, 0x44, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x72, 0x64, 0x20, - 0x77, 0x6f, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, - 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, - 0x65, 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x44, 0x65, 0x64, 0x75, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x74, - 0x68, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, - 0x2e, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x20, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x6e, 0x6f, 0x20, 0x64, + 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x55, 0x4d, 0x49, 0x73, 0x2c, 0x20, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x64, + 0x73, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x74, 0x68, 0x20, 0x77, 0x6f, - 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x63, 0x65, - 0x6c, 0x6c, 0x2f, 0x53, 0x4a, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, - 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x4d, 0x4d, 0x5f, 0x43, + 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x72, 0x32, 0x2d, 0x34, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, + 0x68, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x31, 0x4d, 0x4d, 0x20, 0x55, + 0x4d, 0x49, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x69, 0x6e, + 0x67, 0x2e, 0x0a, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x55, 0x4d, 0x49, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x55, 0x4d, + 0x49, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x28, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x73, 0x20, 0x75, + 0x6e, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x79, 0x20, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x73, + 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x73, 0x69, 0x63, 0x20, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x55, 0x4d, 0x49, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x4e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x6f, 0x6d, + 0x6f, 0x70, 0x6f, 0x6c, 0x79, 0x6d, 0x65, 0x72, 0x73, 0x20, 0x28, 0x73, + 0x69, 0x6d, 0x69, 0x6c, 0x61, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x43, 0x65, + 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x32, 0x2e, 0x32, + 0x2e, 0x30, 0x29, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x75, 0x6c, + 0x74, 0x69, 0x47, 0x65, 0x6e, 0x65, 0x55, 0x4d, 0x49, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x73, 0x69, + 0x63, 0x20, 0x2b, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6c, + 0x6f, 0x77, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x55, + 0x4d, 0x49, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x70, + 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, + 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x47, 0x65, 0x6e, + 0x65, 0x55, 0x4d, 0x49, 0x5f, 0x41, 0x6c, 0x6c, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x62, 0x61, 0x73, 0x69, 0x63, 0x20, 0x2b, 0x20, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x55, 0x4d, + 0x49, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x70, 0x20, + 0x74, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6e, + 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x2e, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x47, 0x65, 0x6e, 0x65, + 0x55, 0x4d, 0x49, 0x5f, 0x43, 0x52, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, + 0x2e, 0x20, 0x62, 0x61, 0x73, 0x69, 0x63, 0x20, 0x2b, 0x20, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x2d, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x55, 0x4d, 0x49, 0x73, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x6f, + 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x67, 0x65, 0x6e, 0x65, 0x2c, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, + 0x6e, 0x67, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x72, 0x20, 0x3e, 0x20, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x20, 0x2e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x73, 0x6f, 0x6c, + 0x6f, 0x55, 0x4d, 0x49, 0x64, 0x65, 0x64, 0x75, 0x70, 0x20, 0x31, 0x4d, + 0x4d, 0x5f, 0x43, 0x52, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x73, 0x6f, 0x6c, 0x6f, 0x4f, 0x75, + 0x74, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x6f, + 0x6c, 0x6f, 0x2e, 0x6f, 0x75, 0x74, 0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x2e, 0x74, 0x73, 0x76, 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, + 0x65, 0x73, 0x2e, 0x74, 0x73, 0x76, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x2e, 0x6d, 0x74, 0x78, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, + 0x73, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x54, 0x41, 0x52, + 0x73, 0x6f, 0x6c, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x3a, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x36, 0x74, 0x68, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x2e, 0x2e, 0x2e, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x2f, 0x47, 0x65, 0x6e, - 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, - 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, 0x0a + 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x20, 0x20, + 0x67, 0x65, 0x6e, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x20, + 0x20, 0x62, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x20, 0x20, 0x63, 0x65, 0x6c, + 0x6c, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, 0x0a, + 0x73, 0x6f, 0x6c, 0x6f, 0x43, 0x65, 0x6c, 0x6c, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x72, 0x32, 0x2e, 0x32, 0x20, 0x33, 0x30, 0x30, 0x30, 0x20, 0x30, + 0x2e, 0x39, 0x39, 0x20, 0x31, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, + 0x65, 0x6c, 0x6c, 0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x4e, 0x6f, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x64, 0x6f, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x63, 0x65, 0x6c, + 0x6c, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x6f, 0x70, 0x43, 0x65, + 0x6c, 0x6c, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, + 0x2e, 0x2e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, + 0x20, 0x62, 0x79, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x2c, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, + 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x65, 0x6c, + 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x32, 0x2e, 0x32, 0x20, 0x20, + 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, + 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, + 0x32, 0x2e, 0x32, 0x2e, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, + 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x62, 0x79, + 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x2c, 0x20, + 0x72, 0x6f, 0x62, 0x75, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, + 0x75, 0x6d, 0x20, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x6c, + 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x55, 0x4d, 0x49, 0x20, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x20, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x55, 0x4d, + 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, + 0x68, 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, + 0x20, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x3a, + 0x20, 0x6e, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x65, + 0x6c, 0x6c, 0x73, 0x3d, 0x33, 0x30, 0x30, 0x30, 0x3b, 0x20, 0x20, 0x6d, + 0x61, 0x78, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, + 0x3d, 0x30, 0x2e, 0x39, 0x39, 0x3b, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x4d, + 0x69, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x3d, 0x31, 0x30, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x44, 0x72, 0x6f, 0x70, + 0x73, 0x5f, 0x43, 0x52, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x44, 0x72, 0x6f, 0x70, 0x73, 0x20, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x43, + 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x66, 0x6c, + 0x61, 0x76, 0x6f, 0x72, 0x2e, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x20, 0x63, 0x69, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, + 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x44, 0x72, 0x6f, 0x70, 0x73, 0x20, 0x70, 0x61, 0x70, 0x65, 0x72, 0x3a, + 0x20, 0x41, 0x2e, 0x54, 0x2e, 0x4c, 0x20, 0x4c, 0x75, 0x6e, 0x20, 0x65, + 0x74, 0x20, 0x61, 0x6c, 0x2c, 0x20, 0x47, 0x65, 0x6e, 0x6f, 0x6d, 0x65, + 0x20, 0x42, 0x69, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x2c, 0x20, 0x32, 0x30, + 0x2c, 0x20, 0x36, 0x33, 0x20, 0x28, 0x32, 0x30, 0x31, 0x39, 0x29, 0x3a, + 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x65, 0x6e, + 0x6f, 0x6d, 0x65, 0x62, 0x69, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x2e, 0x62, + 0x69, 0x6f, 0x6d, 0x65, 0x64, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, + 0x73, 0x2f, 0x31, 0x30, 0x2e, 0x31, 0x31, 0x38, 0x36, 0x2f, 0x73, 0x31, + 0x33, 0x30, 0x35, 0x39, 0x2d, 0x30, 0x31, 0x39, 0x2d, 0x31, 0x36, 0x36, + 0x32, 0x2d, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x66, + 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x31, + 0x30, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x20, 0x6e, + 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x43, 0x65, 0x6c, 0x6c, + 0x73, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x50, 0x65, 0x72, 0x63, 0x65, + 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x4d, + 0x69, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x20, 0x20, 0x20, 0x69, 0x6e, + 0x64, 0x4d, 0x69, 0x6e, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x64, 0x4d, 0x61, + 0x78, 0x20, 0x20, 0x20, 0x75, 0x6d, 0x69, 0x4d, 0x69, 0x6e, 0x20, 0x20, + 0x20, 0x75, 0x6d, 0x69, 0x4d, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x63, 0x4d, + 0x65, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x20, 0x20, 0x63, 0x61, 0x6e, 0x64, + 0x4d, 0x61, 0x78, 0x4e, 0x20, 0x20, 0x20, 0x46, 0x44, 0x52, 0x20, 0x20, + 0x20, 0x73, 0x69, 0x6d, 0x4e, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x68, + 0x61, 0x72, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x3a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x33, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x39, 0x39, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, + 0x20, 0x20, 0x34, 0x35, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x39, + 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, + 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x32, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x30, 0x2e, 0x30, + 0x31, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x73, 0x6f, + 0x6c, 0x6f, 0x4f, 0x75, 0x74, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x33, 0x20, 0x20, 0x20, 0x20, 0x22, 0x47, 0x65, + 0x6e, 0x65, 0x20, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x28, 0x73, 0x29, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x20, 0x33, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x47, 0x65, 0x6e, 0x65, 0x20, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x2e, 0x74, 0x73, 0x76, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x20, + 0x49, 0x66, 0x20, 0x22, 0x2d, 0x22, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, + 0x20, 0x6e, 0x6f, 0x20, 0x33, 0x72, 0x64, 0x20, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2e, + 0x0a, 0x0a, 0x23, 0x23, 0x23, 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, + 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20, 0x3a, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x2d, 0x20, + 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x0a, 0x73, + 0x6f, 0x6c, 0x6f, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x42, + 0x66, 0x69, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x2d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x20, 0x62, 0x61, + 0x72, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, + 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3a, 0x20, 0x43, 0x42, 0x20, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x2d, 0x2d, 0x73, 0x6f, 0x6c, 0x6f, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x33, 0x70, 0x0a, 0x23, 0x23, + 0x23, 0x23, 0x23, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x44, 0x65, 0x76, 0x65, + 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x0a }; -unsigned int parametersDefault_len = 38385; +unsigned int parametersDefault_len = 54420; diff --git a/source/readBarcodeLoad.h b/source/readBarcodeLoad.h new file mode 100644 index 00000000..8daf1480 --- /dev/null +++ b/source/readBarcodeLoad.h @@ -0,0 +1,9 @@ +#ifndef H_readBarcodeLoad +#define H_readBarcodeLoad + +#include "IncludeDefine.h" +#include "Parameters.h" + +void loadBarcodeRead(Parameters &P, istream **readInStream, string &seq1, string &qual1); + +#endif diff --git a/source/readLoad.cpp b/source/readLoad.cpp index 29c621a7..4adc9537 100644 --- a/source/readLoad.cpp +++ b/source/readLoad.cpp @@ -1,120 +1,71 @@ #include "readLoad.h" #include "ErrorWarning.h" -int readLoad(istream& readInStream, Parameters& P, uint iMate, uint& Lread, uint& LreadOriginal, char* readName, char* Seq, char* SeqNum, char* Qual, char* QualNum, uint &clip3pNtotal, uint &clip5pNtotal, uint &clip3pAdapterN, uint &iReadAll, uint &readFilesIndex, char &readFilter, string &readNameExtra){ - //load one read from a stream +int readLoad(istream& readInStream, Parameters& P, uint& Lread, uint& LreadOriginal, \ + char* readName, char* Seq, char* SeqNum, char* Qual, vector &clipOneMate, \ + uint &iReadAll, uint32 &readFilesIndex, char &readFilter, string &readNameExtra) +{//load one read from a stream int readFileType=0; -// readInStream.getline(readName,DEF_readNameLengthMax); //extract name - - if (readInStream.peek()!='@' && readInStream.peek()!='>') return -1; //end of the stream + if (readInStream.peek()!='@' && readInStream.peek()!='>') + return -1; //end of the stream + string line1; + + getline(readInStream, line1); //read 1st line + istringstream line1str(line1); + readName[0]=0;//clear char array - readInStream >> readName; //TODO check that it does not overflow the array + line1str >> readName; //TODO check that it does not overflow the array if (strlen(readName)>=DEF_readNameLengthMax-1) { ostringstream errOut; - errOut << "EXITING because of FATAL ERROR in reads input: read name is too long:" << readInStream.gcount()<<"\n"; - errOut << "Read Name="<logMain, EXIT_CODE_INPUT_FILES, P); - }; - - readInStream >> iReadAll >> readFilter >> readFilesIndex; //extract read number - - getline(readInStream, readNameExtra); - if (!readNameExtra.empty()) { - size_t n1=readNameExtra.find_first_not_of(" \t"); - if (n1!=std::string::npos) { - readNameExtra=readNameExtra.substr(n1); - } else { - readNameExtra=""; - }; - }; - -// readInStream.ignore(DEF_readNameSeqLengthMax,'\n');//ignore the resit of the line - just in case + }; + + line1str >> iReadAll >> readFilter >> readFilesIndex; //extract read number TODO this is needed only for one mate + line1str >> std::ws; //skip whitespace before readNameExtra + getline(line1str, readNameExtra); readInStream.getline(Seq,DEF_readSeqLengthMax+1); //extract sequence - Lread=0; - for (int ii=0; ii=32) { - Seq[Lread]=Seq[ii]; - ++Lread; - }; - }; + Lread=readInStream.gcount()-1; if (Lread<1) { ostringstream errOut; errOut << "EXITING because of FATAL ERROR in reads input: short read sequence line: " << Lread <<"\n"; - errOut << "Read Name="<=" << Lread << " while DEF_readSeqLengthMax=" << DEF_readSeqLengthMax <<"\n"; - errOut << "Read Name="<=" << Lread << " while DEF_readSeqLengthMax=" << DEF_readSeqLengthMax <<'\n'<< "Read Name="<logMain, EXIT_CODE_INPUT_FILES, P); }; -// //was trying to read multi-line -// char nextChar='A'; -// Lread=0; -// while (nextChar!='@' && nextChar!='>' && nextChar!='+' && nextChar!=' ' && nextChar!='\n' && !readInStream.eof()) {//read multi-line fasta -// readInStream.getline(Seq+Lread,DEF_readSeqLengthMax+1); //extract sequence -// Lread+=(uint) readInStream.gcount() - 1; //count chars in the sequence line, but do not read yet -// nextChar=readInStream.peek(); -// }; -// if (Lread>DEF_readSeqLengthMax) { -// ostringstream errOut; -// errOut << "EXITING because of FATAL ERROR in reads input: Lread>=" << Lread << " while DEF_readSeqLengthMax=" << DEF_readSeqLengthMax <<"\n"; -// errOut << "Read Name="<logMain, EXIT_CODE_INPUT_FILES, P); -// }; -// LreadOriginal=Lread; - LreadOriginal=Lread; - if ( Lread>(P.clip5pNbases[iMate]+P.clip3pNbases[iMate]) ) { - Lread=Lread-(P.clip5pNbases[iMate]+P.clip3pNbases[iMate]); - } else { - Lread=0; - }; - convertNucleotidesToNumbersRemoveControls(Seq+P.clip5pNbases[iMate],SeqNum,Lread); - //clip the adapter - if (P.clip3pAdapterSeq.at(iMate).length()>0) { - clip3pAdapterN = Lread-localSearch(SeqNum,Lread,P.clip3pAdapterSeqNum[iMate],P.clip3pAdapterSeq.at(iMate).length(),P.clip3pAdapterMMp[iMate]); - Lread = Lread>clip3pAdapterN ? Lread-clip3pAdapterN : 0; - } else { - clip3pAdapterN = 0; - }; - - //final read length, trim 3p after the adapter was clipped - if (Lread>P.clip3pAfterAdapterNbases[iMate]) { - Lread =Lread - P.clip3pAfterAdapterNbases[iMate]; - } else { - Lread=0; + convertNucleotidesToNumbers(Seq,SeqNum,Lread); + + if (readName[0]=='@') {//fastq format: read the '+' line + readFileType=2; + readInStream.get(clipOneMate[0].clippedInfo); //this is used if clipChunk is activated, only 5' for now + readInStream.ignore(); //ignore one char: \n }; - clip3pNtotal=P.clip3pNbases[iMate] + clip3pAdapterN + P.clip3pAfterAdapterNbases[iMate]; - clip5pNtotal=P.clip5pNbases[iMate]; + //cout << readName <<'\t' << (uint32) line3char << '\n'; + + clipOneMate[0].clip(Lread, SeqNum); //5p clip + clipOneMate[1].clip(Lread, SeqNum); //3p clip if (readName[0]=='@') {//fastq format, read qualities - readFileType=2; - readInStream.ignore(DEF_readNameLengthMax,'\n'); //extract header line readInStream.getline(Qual,DEF_readSeqLengthMax);//read qualities if ((uint) readInStream.gcount() != LreadOriginal+1) {//inconsistent read sequence and quality ostringstream errOut; errOut << "EXITING because of FATAL ERROR in reads input: quality string length is not equal to sequence length\n"; - errOut << readName<<"\n"; - errOut << Seq <<"\n"; - errOut << Qual <<"\n"; - errOut << "SOLUTION: fix your fastq file\n"; + errOut << readName <<'\n'<< Seq <<'\n'<< Qual <<'\n'<< "SOLUTION: fix your fastq file\n"; exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); }; if (P.outQSconversionAdd!=0) { @@ -128,38 +79,20 @@ int readLoad(istream& readInStream, Parameters& P, uint iMate, uint& Lread, uint Qual[ii]=qs; }; }; - + } else if (readName[0]=='>') {//fasta format, assign Qtop to all qualities readFileType=1; - for (uint ii=0;ii : "<< readName<<"\n"; exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_INPUT_FILES, P); }; - for (uint ii=0;ii P.QasciiSubtract) ? (Qual[ii+P.clip5pNbases[iMate]] - P.QasciiSubtract) : 0; //substract QasciiSubtract -// QualNum[ii]=P.QSconv[(int) QualNum[ii]]; -// QualNum[ii]=min(QualNum[ii], P.Qtop);//cut QSs at the Qtop -// // if (QualNum[ii]==2) QualNum[ii]=P.Qtop; -// if (SeqNum[ii]>3) QualNum[ii]=0; //QS=0 for Ns -// Qual1[1][Lread-ii-1]=QualNum[ii]; //reverse -// }; - - - //trim read name - for (uint ii=0; ii &clipOneMate, \ + uint &iReadAll, uint32 &readFilesIndex, char &readFilter, string &readNameExtra); #endif diff --git a/source/samHeaders.cpp b/source/samHeaders.cpp new file mode 100644 index 00000000..01bea49c --- /dev/null +++ b/source/samHeaders.cpp @@ -0,0 +1,108 @@ +#include "samHeaders.h" +#include +#include "BAMfunctions.h" + +void samHeaders(Parameters &P, Genome &genomeOut, Transcriptome &transcriptomeMain) +{ + /////////////////////////////////////////////////////////////////////////////////// transcriptome BAM header + if ( P.quant.trSAM.bamYes ) {//header for transcriptome BAM + ostringstream samHeaderStream; + vector trlength; + for (uint32 ii=0;iioutQuantBAMfile,samHeaderStream.str(),transcriptomeMain.trID,trlength); + }; + + //////////////////////////////////////////////////////////////////////////////// main headers + if (P.outSAMmode == "None" || P.outSAMtype[0] == "None") {//no SAM output + return; + }; + + ostringstream samHeaderStream; + + for (uint ii=0;ii> field1;//should check for @SQ + + if (field1!="") {//skip blank lines + samHeaderStream << line1 <<"\n"; + + stream1 >> field1; + genomeOut.chrNameAll.push_back(field1.substr(3)); + stream1 >> field1; + genomeOut.chrLengthAll.push_back((uint) stoll(field1.substr(3))); + }; + }; + extrastream.close(); + }; + + if (P.outSAMheaderPG.at(0)!="-") { + samHeaderStream << P.outSAMheaderPG.at(0); + for (uint ii=1;iioutSAM << P.samHeader; + }; + if (P.outBAMunsorted){ + outBAMwriteHeader(P.inOut->outBAMfileUnsorted,P.samHeader,genomeOut.chrNameAll,genomeOut.chrLengthAll); + }; +}; \ No newline at end of file diff --git a/source/samHeaders.h b/source/samHeaders.h new file mode 100644 index 00000000..b2089f6c --- /dev/null +++ b/source/samHeaders.h @@ -0,0 +1,10 @@ +#ifndef H_samHeaders +#define H_samHeaders + +#include "Parameters.h" +#include "Genome.h" +#include "Transcriptome.h" + +void samHeaders(Parameters &P, Genome &genomeMain, Transcriptome &transcriptomeMain); + +#endif \ No newline at end of file diff --git a/source/serviceFuns.cpp b/source/serviceFuns.cpp index 08dcde7a..3b41bfc0 100644 --- a/source/serviceFuns.cpp +++ b/source/serviceFuns.cpp @@ -36,6 +36,19 @@ template int funCompareNumbersReverse (const void *a, const void *b }; }; +template int funCompareNumbersReverseShift (const void *a, const void *b) { + numT va= *((numT*) a + Shift); + numT vb= *((numT*) b + Shift); + + if (va>vb) { + return -1; + } else if (va==vb) { + return 0; + } else { + return 1; + }; +}; + inline int funCompareUint1 (const void *a, const void *b) { uint va= *((uint*) a); @@ -84,18 +97,70 @@ inline int funCompareArrays (const void *a, const void *b) { }; +template +inline int funCompareArraysReverse (const void *a, const void *b) { + arrayType* va= (arrayType*) a; + arrayType* vb= (arrayType*) b; + + for (int ii=0;iivb[ii]) { + return -1; + } else if (va[ii] +inline int funCompareArraysShift (const void *a, const void *b) { + arrayType* va= ((arrayType*) a) + Shift; + arrayType* vb= ((arrayType*) b) + Shift; + + for (int ii=0;iivb[ii]) { + return 1; + } else if (va[ii] +inline int funCompareTypeSecondFirst (const void *a, const void *b) { + Type va= *( ((Type*) a) + 1 ); + Type vb= *( ((Type*) b) + 1 ); + Type va1= *( ((Type*) a) + 0 ); + Type vb1= *( ((Type*) b) + 0 ); + + if (va>vb) { + return 1; + } else if (va==vb && va1>vb1) { + return 1; + } else if (va==vb && va1==vb1) { + return 0; + } else { + return -1; + }; +}; + template inline int funCompareTypeShift (const void *a, const void *b) { Type va= *( ((Type*) a)+Shift ); Type vb= *( ((Type*) b)+Shift ); if (va>vb) { - return 1; - } else if (va==vb) { - return 0; - } else { - return -1; - }; + return 1; + } else if (va==vb) { + return 0; + } else { + return -1; + }; }; @@ -108,9 +173,21 @@ inline int splitString(const std::string &s, char delim, std::vector splitString(const std::string &s, char delim) { + std::stringstream ss(s); + std::string item; + std::vector elems; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + }; + return elems; +}; +*/ + template inline uint32 binarySearch1(argType x, argType *X, uint32 N) { //binary search in the sorted list @@ -131,10 +208,38 @@ inline uint32 binarySearch1(argType x, argType *X, uint32 N) { return i1; }; +template +inline bool binarySearch_leLeft(argType x, argType *X, uint32 N, uint32 & i1) { + //binary search in the sorted list + //Retrun false if x is outside of X[0], X[N-1] + //Return i1 = index of the element which is <= x, the leftmost element if equal. + + if (x>X[N-1] || xi1+1) {//binary search + i3=(i1+i2)/2; + if (X[i3]>x) { + i2=i3; + } else {// X[i3] <= x + i1=i3; + }; + }; + + while (i1>0 && x==X[i1-1]) + --i1; //go left to check for equals + + return true; +}; + + template inline int32 binarySearch1a(argType x, argType *X, int32 N) { //binary search in the sorted list //check the boundaries first + //1a returns the last X element that is <= x if (x>X[N-1]) { return N-1; @@ -152,7 +257,8 @@ inline int32 binarySearch1a(argType x, argType *X, int32 N) { }; }; - while (i1 +// inline uint64 binarySearchStride(argType *X, uint64 N, artgType x, iStart, stride ) +// { +// //binary search in the sorted list wit stride +// //1b returns the first X element that is >= x +// //X are all distinct +// //if x>X[N-1], -1 is returned +// +// if (x>X[N-1]) { +// return -1; +// } else if (x<=X[0]) { +// return 0; +// }; +// +// int32 i1=0, i2=N-1, i3=N/2; +// while (i2>i1+1) {//binary search +// i3=(i1+i2)/2; +// if (X[i3]>=x) { +// i2=i3; +// } else { +// i1=i3; +// }; +// }; +// +// return i2; +// }; + #endif diff --git a/source/sjAlignSplit.cpp b/source/sjAlignSplit.cpp old mode 100644 new mode 100755 index 6ba0a2b3..8b7e67a5 --- a/source/sjAlignSplit.cpp +++ b/source/sjAlignSplit.cpp @@ -1,5 +1,4 @@ -#include "IncludeDefine.h" -#include "Genome.h" +#include "sjAlignSplit.h" bool sjAlignSplit(uint a1,uint aLength, const Genome &mapGen, uint &a1D, uint &aLengthD, uint &a1A, uint &aLengthA, uint &isj) { uint sj1=(a1-mapGen.sjGstart)%mapGen.sjdbLength; diff --git a/source/sjAlignSplit.h b/source/sjAlignSplit.h new file mode 100755 index 00000000..ffe38c3c --- /dev/null +++ b/source/sjAlignSplit.h @@ -0,0 +1,9 @@ +#ifndef H_sjAlignSplit +#define H_sjAlignSplit + +#include "IncludeDefine.h" +#include "Genome.h" + +bool sjAlignSplit(uint a1,uint aLength, const Genome &mapGen, uint &a1D, uint &aLengthD, uint &a1A, uint &aLengthA, uint &isj); + +#endif diff --git a/source/sjdbInsertJunctions.cpp b/source/sjdbInsertJunctions.cpp index ff688f99..698d92da 100644 --- a/source/sjdbInsertJunctions.cpp +++ b/source/sjdbInsertJunctions.cpp @@ -3,7 +3,7 @@ #include "sjdbLoadFromFiles.h" #include "sjdbPrepare.h" #include "ErrorWarning.h" -#include "loadGTF.h" +#include "GTF.h" #include "sjdbBuildIndex.h" #include "streamFuns.h" #include "genomeParametersWrite.h" @@ -12,8 +12,8 @@ void sjdbInsertJunctions(Parameters & P, Genome & mapGen, Genome & mapGen1, Sjdb { time_t rawtime; - if (mapGen.sjdbN>0 && sjdbLoci.chr.size()==0) - {//load from the saved genome, only if the loading did not happen already (if sjdb insertion happens at the 1st pass, sjdbLoci will be populated + if (mapGen.sjdbN>0 && sjdbLoci.chr.size()==0) { + //load from the saved genome, only if the loading did not happen already (if sjdb insertion happens at the 1st pass, sjdbLoci will be populated ifstream & sjdbStreamIn = ifstrOpen(P.pGe.gDir+"/sjdbList.out.tab", ERROR_OUT, "SOLUTION: re-generate the genome in pGe.gDir=" + P.pGe.gDir, P); sjdbLoadFromStream(sjdbStreamIn, sjdbLoci); sjdbLoci.priority.resize(sjdbLoci.chr.size(),30); @@ -21,9 +21,9 @@ void sjdbInsertJunctions(Parameters & P, Genome & mapGen, Genome & mapGen1, Sjdb P.inOut->logMain << timeMonthDayTime(rawtime) << " Loaded database junctions from the generated genome " << P.pGe.gDir+"/sjdbList.out.tab" <<": "<logMain << timeMonthDayTime(rawtime) << " Loaded database junctions from the 1st pass file: " << P.twoPass.pass1sjFile <<": "<logMain << timeMonthDayTime(rawtime) << " Loaded database junctions from the pGe.sjdbFileChrStartEnd file(s), " << sjdbLoci.chr.size()<<" total junctions\n\n"; - }; - - if (P.pGe.sjdbGTFfile!="-") - {//load from GTF - loadGTF(sjdbLoci, P, P.sjdbInsert.outDir, mapGen); - sjdbLoci.priority.resize(sjdbLoci.chr.size(),20); - time ( &rawtime ); - P.inOut->logMain << timeMonthDayTime(rawtime) << " Loaded database junctions from the GTF file: " << P.pGe.sjdbGTFfile<<": "<logMain << timeMonthDayTime(rawtime) << " Finished preparing junctions" <logMain << "Loaded database junctions from file: " << P.pGe.sjdbFileChrStartEnd.at(ifile) <<", total number of junctions: "<logMain << timeMonthDayTime(rawtime) << " Loaded database junctions from the pGe.sjdbFileChrStartEnd file(s), total number of junctions:" << sjdbLoci.chr.size()<<"\n\n"; }; }; //if (P.pGe.sjdbFileChrStartEnd!="-") diff --git a/source/sjdbPrepare.cpp b/source/sjdbPrepare.cpp old mode 100644 new mode 100755 diff --git a/source/soloInputFeatureUMI.cpp b/source/soloInputFeatureUMI.cpp new file mode 100644 index 00000000..85336eff --- /dev/null +++ b/source/soloInputFeatureUMI.cpp @@ -0,0 +1,42 @@ +#include "soloInputFeatureUMI.h" +#include "SoloReadFeature.h" +#include "binarySearch2.h" + +bool soloInputFeatureUMI(fstream *strIn, int32 featureType, bool readInfoYes, array,2> &sjAll, uint64 &iread, int32 &cbmatch, uint32 &feature, uint64 &umi, vector &featVecU32) +{ + if (!(*strIn >> umi)) //end of file + return false; + + if (readInfoYes) + *strIn >> iread; + + switch (featureType) { + case SoloFeatureTypes::Gene : + case SoloFeatureTypes::GeneFull : + case SoloFeatureTypes::GeneFull_Ex50pAS : + case SoloFeatureTypes::GeneFull_ExonOverIntron : + *strIn >> feature; + break; + + case SoloFeatureTypes::SJ : + uint64 sj[2]; + *strIn >> sj[0] >> sj[1]; + feature=(uint32) binarySearch2(sj[0],sj[1],sjAll[0].data(),sjAll[1].data(),sjAll[0].size()); + break; + + case SoloFeatureTypes::Transcript3p : + feature=0; + uint32 ntr, in1; + *strIn >> ntr; + featVecU32.resize(2*ntr); + for (uint32 ii=0; ii<2*ntr; ii++) { + *strIn >> in1; + featVecU32[ii]=in1; + }; + break; + }; + + *strIn >> cbmatch; + + return true; +}; \ No newline at end of file diff --git a/source/soloInputFeatureUMI.h b/source/soloInputFeatureUMI.h new file mode 100644 index 00000000..4510999c --- /dev/null +++ b/source/soloInputFeatureUMI.h @@ -0,0 +1,11 @@ +#ifndef H_soloInputFeatureUMI +#define H_soloInputFeatureUMI + +#include +#include +#include +#include "IncludeDefine.h" + +bool soloInputFeatureUMI(fstream *strIn, int32 featureType, bool readInfoYes, array,2> &sjAll, uint64 &iread, int32 &cbmatch, uint32 &feature, uint64 &umi, vector &featVecU32); + +#endif diff --git a/source/stitchAlignToTranscript.cpp b/source/stitchAlignToTranscript.cpp index 84bb427a..c6bd9d16 100644 --- a/source/stitchAlignToTranscript.cpp +++ b/source/stitchAlignToTranscript.cpp @@ -215,9 +215,14 @@ intScore stitchAlignToTranscript(uint rAend, uint gAend, uint rBstart, uint gBst jCan=mapGen.sjdbMotif[sjdbInd]; if (mapGen.sjdbMotif[sjdbInd]==0) {//shift to match annotations if (L<=mapGen.sjdbShiftLeft[sjdbInd] || trA->exons[trA->nExons-1][EX_L]<=mapGen.sjdbShiftLeft[sjdbInd]) { + //this is not needed, the check below rAend+jR >= rBend is enough + //it changes the results slightly, so will keep for now. Will remove in STAR3 return -1000006; }; jR += (int) mapGen.sjdbShiftLeft[sjdbInd]; + if ( rAend+jR >= rBend ) {//jR is shifted past rBend + return -1000006; + }; jjL=mapGen.sjdbShiftLeft[sjdbInd]; jjR=mapGen.sjdbShiftRight[sjdbInd]; }; diff --git a/source/stitchWindowAligns.cpp b/source/stitchWindowAligns.cpp old mode 100644 new mode 100755 index 301e2ae3..c8551bef --- a/source/stitchWindowAligns.cpp +++ b/source/stitchWindowAligns.cpp @@ -110,11 +110,13 @@ void stitchWindowAligns(uint iA, uint nA, int Score, bool WAincl[], uint tR2, ui //filter strand consistency uint sjN=0; trA.intronMotifs[0]=0;trA.intronMotifs[1]=0;trA.intronMotifs[2]=0; + trA.sjYes=false; for (uint iex=0;iex=0) {//junctions - others are indels sjN++; trA.intronMotifs[trA.sjStr[iex]]++; + trA.sjYes=true; }; }; diff --git a/source/stitchWindowAligns.h b/source/stitchWindowAligns.h old mode 100644 new mode 100755 diff --git a/source/streamFuns.cpp b/source/streamFuns.cpp index 1313922a..9031529c 100644 --- a/source/streamFuns.cpp +++ b/source/streamFuns.cpp @@ -5,6 +5,36 @@ #include #include #define fstream_Chunk_Max 2147483647 +#include + +void createDirectory(const string dirPathIn, const mode_t dirPerm, const string dirParameter, Parameters &P) +{ + string dirPath = dirPathIn.substr(0,dirPathIn.find_last_of('/')+1); + if (mkdir(dirPath.c_str(), dirPerm) == -1) { + if ( errno == EEXIST ) {//directory exists + P.inOut->logMain << dirParameter << " directory exists and will be overwritten: " << dirPath <logMain, EXIT_CODE_PARAMETER, P); + }; + }; + i1=dirPath.find_first_of('/',i1+1); + }; + P.inOut->logMain << dirParameter << " directory and its parents created: " << dirPath <logMain << dirParameter << " directory created: " << dirPath <fail()) //did not work <= file does not exist => open with trunc (the above command does not work on new file) + fStreamP = new std::fstream(fileName.c_str(), std::fstream::in | std::fstream::out | std::fstream::trunc); + }; + + if (fStreamP->fail()) {// ostringstream errOut; errOut << errorID<<": exiting because of *OUTPUT FILE* error: could not create input/output file "<< fileName <<"\n"; errOut << "Solution: check that the path exists and you have write permission for this file\n"; exitWithError(errOut.str(),std::cerr, P.inOut->logMain, EXIT_CODE_FILE_OPEN, P); }; - return fStream; + return *fStreamP; }; std::ifstream & ifstrOpen (std::string fileName, std::string errorID, std::string solutionString, Parameters &P) { diff --git a/source/streamFuns.h b/source/streamFuns.h index 899bb944..7057ec58 100644 --- a/source/streamFuns.h +++ b/source/streamFuns.h @@ -7,10 +7,11 @@ unsigned long long fstreamReadBig(std::ifstream &S, char* A, unsigned long long N); void fstreamWriteBig(std::ofstream &S, char* A, unsigned long long N, std::string fileName, std::string errorID, Parameters &P) ; -fstream &fstrOpen (std::string fileName, std::string errorID, Parameters &P); +fstream &fstrOpen (std::string fileName, std::string errorID, Parameters &P, bool flagDelete); ofstream &ofstrOpen (std::string fileName, std::string errorID, Parameters &P); ifstream &ifstrOpen (std::string fileName, std::string errorID, std::string solutionString, Parameters &P); ifstream &ifstrOpenGenomeFile (std::string fileName, std::string errorID, Parameters &P); +void createDirectory(const string dirPathIn, const mode_t dirPerm, const string dirParameter, Parameters &P); void copyFile(string fileIn, string fileOut); #endif diff --git a/source/twoPassRunPass1.cpp b/source/twoPassRunPass1.cpp new file mode 100644 index 00000000..5ebf545b --- /dev/null +++ b/source/twoPassRunPass1.cpp @@ -0,0 +1,77 @@ +#include "twoPassRunPass1.h" +#include "mapThreadsSpawn.h" +#include "ReadAlignChunk.h" +#include "Stats.h" +#include "GlobalVariables.h" +#include "outputSJ.h" +#include "sjdbInsertJunctions.h" + +void twoPassRunPass1(Parameters &P, Genome &genomeMain, Transcriptome *transcriptomeMain, SjdbClass &sjdbLoci) //2-pass: 1st pass +{ + if (!P.twoPass.yes) + return; + + //re-define P and genomeMain for the pass1 + Genome genomeMain1=genomeMain; + + Parameters P1=P; + //turn off unnecessary calculations + P1.outSAMtype[0]="None"; + P1.outSAMbool=false; + P1.outBAMunsorted=false; + P1.outBAMcoord=false; + + P1.pCh.segmentMin=0; + + P1.quant.yes=false; + P1.quant.trSAM.yes=false; + P1.quant.trSAM.bamYes=false; + P1.quant.geneFull.yes=false; + P1.quant.geCount.yes=false; + P1.quant.gene.yes=false; + + P1.outSAMunmapped.within=false; + + P1.outFilterBySJoutStage=0; + + P1.outReadsUnmapped="None"; + + P1.outFileNamePrefix=P.twoPass.dir; + + P1.readMapNumber=min(P.twoPass.pass1readsN, P.readMapNumber); +// P1.inOut->logMain.open((P1.outFileNamePrefix + "Log.out").c_str()); + + P1.wasp.outputMode="None"; //no WASP filtering on the 1st pass + P1.pSolo.type=P1.pSolo.SoloTypes::None; //no solo in the first pass + + g_statsAll.resetN(); + time(&g_statsAll.timeStartMap); + P.inOut->logProgress << timeMonthDayTime(g_statsAll.timeStartMap) <<"\tStarted 1st pass mapping\n" <logStdOut << timeMonthDayTime(g_statsAll.timeStartMap) << " ..... started 1st pass mapping\n" <logProgress << timeMonthDayTime(rawtime) <<"\tFinished 1st pass mapping\n"; + *P.inOut->logStdOut << timeMonthDayTime(rawtime) << " ..... finished 1st pass mapping\n" <