|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712 |
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2022 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- The code included in this file is provided under the terms of the ISC license
- http://www.isc.org/downloads/software-support-policy/isc-license. Permission
- To use, copy, modify, and/or distribute this software for any purpose with or
- without fee is hereby granted provided that the above copyright notice and
- this permission notice appear in all copies.
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- namespace FloatVectorHelpers
- {
- #define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
- #define JUCE_INCREMENT_SRC1_SRC2_DEST dest += (16 / sizeof (*dest)); src1 += (16 / sizeof (*dest)); src2 += (16 / sizeof (*dest));
- #define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
-
- #if JUCE_USE_SSE_INTRINSICS
- static bool isAligned (const void* p) noexcept
- {
- return (((pointer_sized_int) p) & 15) == 0;
- }
-
- struct BasicOps32
- {
- using Type = float;
- using ParallelType = __m128;
- using IntegerType = __m128;
- enum { numParallel = 4 };
-
- // Integer and parallel types are the same for SSE. On neon they have different types
- static forcedinline IntegerType toint (ParallelType v) noexcept { return v; }
- static forcedinline ParallelType toflt (IntegerType v) noexcept { return v; }
-
- static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_ps (&v); }
- static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_ps (v); }
- static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_ps (v); }
- static forcedinline void storeA (Type* dest, ParallelType a) noexcept { _mm_store_ps (dest, a); }
- static forcedinline void storeU (Type* dest, ParallelType a) noexcept { _mm_storeu_ps (dest, a); }
-
- static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return _mm_add_ps (a, b); }
- static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return _mm_sub_ps (a, b); }
- static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return _mm_mul_ps (a, b); }
- static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_ps (a, b); }
- static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_ps (a, b); }
-
- static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_ps (a, b); }
- static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_ps (a, b); }
- static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_ps (a, b); }
- static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_ps (a, b); }
-
- static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); }
- static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); }
- };
-
- struct BasicOps64
- {
- using Type = double;
- using ParallelType = __m128d;
- using IntegerType = __m128d;
- enum { numParallel = 2 };
-
- // Integer and parallel types are the same for SSE. On neon they have different types
- static forcedinline IntegerType toint (ParallelType v) noexcept { return v; }
- static forcedinline ParallelType toflt (IntegerType v) noexcept { return v; }
-
- static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_pd (&v); }
- static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_pd (v); }
- static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_pd (v); }
- static forcedinline void storeA (Type* dest, ParallelType a) noexcept { _mm_store_pd (dest, a); }
- static forcedinline void storeU (Type* dest, ParallelType a) noexcept { _mm_storeu_pd (dest, a); }
-
- static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return _mm_add_pd (a, b); }
- static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return _mm_sub_pd (a, b); }
- static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return _mm_mul_pd (a, b); }
- static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_pd (a, b); }
- static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_pd (a, b); }
-
- static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_pd (a, b); }
- static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_pd (a, b); }
- static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_pd (a, b); }
- static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_pd (a, b); }
-
- static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1]); }
- static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1]); }
- };
-
-
-
- #define JUCE_BEGIN_VEC_OP \
- using Mode = FloatVectorHelpers::ModeType<sizeof(*dest)>::Mode; \
- { \
- const auto numLongOps = num / Mode::numParallel;
-
- #define JUCE_FINISH_VEC_OP(normalOp) \
- num &= (Mode::numParallel - 1); \
- if (num == 0) return; \
- } \
- for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
-
- #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- if (FloatVectorHelpers::isAligned (dest)) JUCE_VEC_LOOP (vecOp, dummy, Mode::loadA, Mode::storeA, locals, JUCE_INCREMENT_DEST) \
- else JUCE_VEC_LOOP (vecOp, dummy, Mode::loadU, Mode::storeU, locals, JUCE_INCREMENT_DEST) \
- JUCE_FINISH_VEC_OP (normalOp)
-
- #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- if (FloatVectorHelpers::isAligned (dest)) \
- { \
- if (FloatVectorHelpers::isAligned (src)) JUCE_VEC_LOOP (vecOp, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
- else JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
- }\
- else \
- { \
- if (FloatVectorHelpers::isAligned (src)) JUCE_VEC_LOOP (vecOp, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
- else JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- } \
- JUCE_FINISH_VEC_OP (normalOp)
-
- #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- if (FloatVectorHelpers::isAligned (dest)) \
- { \
- if (FloatVectorHelpers::isAligned (src1)) \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadU, Mode::storeA, locals, increment) \
- } \
- else \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeA, locals, increment) \
- } \
- } \
- else \
- { \
- if (FloatVectorHelpers::isAligned (src1)) \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadA, Mode::storeU, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
- } \
- else \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadA, Mode::storeU, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- } \
- } \
- JUCE_FINISH_VEC_OP (normalOp)
-
- #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- if (FloatVectorHelpers::isAligned (dest)) \
- { \
- if (FloatVectorHelpers::isAligned (src1)) \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
- } \
- else \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \
- } \
- } \
- else \
- { \
- if (FloatVectorHelpers::isAligned (src1)) \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- } \
- else \
- { \
- if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \
- else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- } \
- } \
- JUCE_FINISH_VEC_OP (normalOp)
-
-
- //==============================================================================
- #elif JUCE_USE_ARM_NEON
-
- struct BasicOps32
- {
- using Type = float;
- using ParallelType = float32x4_t;
- using IntegerType = uint32x4_t;
- union signMaskUnion { ParallelType f; IntegerType i; };
- enum { numParallel = 4 };
-
- static forcedinline IntegerType toint (ParallelType v) noexcept { signMaskUnion u; u.f = v; return u.i; }
- static forcedinline ParallelType toflt (IntegerType v) noexcept { signMaskUnion u; u.i = v; return u.f; }
-
- static forcedinline ParallelType load1 (Type v) noexcept { return vld1q_dup_f32 (&v); }
- static forcedinline ParallelType loadA (const Type* v) noexcept { return vld1q_f32 (v); }
- static forcedinline ParallelType loadU (const Type* v) noexcept { return vld1q_f32 (v); }
- static forcedinline void storeA (Type* dest, ParallelType a) noexcept { vst1q_f32 (dest, a); }
- static forcedinline void storeU (Type* dest, ParallelType a) noexcept { vst1q_f32 (dest, a); }
-
- static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return vaddq_f32 (a, b); }
- static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return vsubq_f32 (a, b); }
- static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return vmulq_f32 (a, b); }
- static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return vmaxq_f32 (a, b); }
- static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return vminq_f32 (a, b); }
-
- static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return toflt (vandq_u32 (toint (a), toint (b))); }
- static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return toflt (vbicq_u32 (toint (a), toint (b))); }
- static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return toflt (vorrq_u32 (toint (a), toint (b))); }
- static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return toflt (veorq_u32 (toint (a), toint (b))); }
-
- static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); }
- static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); }
- };
-
- struct BasicOps64
- {
- using Type = double;
- using ParallelType = double;
- using IntegerType = uint64;
- union signMaskUnion { ParallelType f; IntegerType i; };
- enum { numParallel = 1 };
-
- static forcedinline IntegerType toint (ParallelType v) noexcept { signMaskUnion u; u.f = v; return u.i; }
- static forcedinline ParallelType toflt (IntegerType v) noexcept { signMaskUnion u; u.i = v; return u.f; }
-
- static forcedinline ParallelType load1 (Type v) noexcept { return v; }
- static forcedinline ParallelType loadA (const Type* v) noexcept { return *v; }
- static forcedinline ParallelType loadU (const Type* v) noexcept { return *v; }
- static forcedinline void storeA (Type* dest, ParallelType a) noexcept { *dest = a; }
- static forcedinline void storeU (Type* dest, ParallelType a) noexcept { *dest = a; }
-
- static forcedinline ParallelType add (ParallelType a, ParallelType b) noexcept { return a + b; }
- static forcedinline ParallelType sub (ParallelType a, ParallelType b) noexcept { return a - b; }
- static forcedinline ParallelType mul (ParallelType a, ParallelType b) noexcept { return a * b; }
- static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return jmax (a, b); }
- static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return jmin (a, b); }
-
- static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) & toint (b)); }
- static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return toflt ((~toint (a)) & toint (b)); }
- static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) | toint (b)); }
- static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) ^ toint (b)); }
-
- static forcedinline Type max (ParallelType a) noexcept { return a; }
- static forcedinline Type min (ParallelType a) noexcept { return a; }
- };
-
- #define JUCE_BEGIN_VEC_OP \
- using Mode = FloatVectorHelpers::ModeType<sizeof(*dest)>::Mode; \
- if (Mode::numParallel > 1) \
- { \
- const auto numLongOps = num / Mode::numParallel;
-
- #define JUCE_FINISH_VEC_OP(normalOp) \
- num &= (Mode::numParallel - 1); \
- if (num == 0) return; \
- } \
- for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
-
- #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- JUCE_VEC_LOOP (vecOp, dummy, Mode::loadU, Mode::storeU, locals, JUCE_INCREMENT_DEST) \
- JUCE_FINISH_VEC_OP (normalOp)
-
- #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- JUCE_FINISH_VEC_OP (normalOp)
-
- #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- JUCE_FINISH_VEC_OP (normalOp)
-
- #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
- JUCE_BEGIN_VEC_OP \
- setupOp \
- JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
- JUCE_FINISH_VEC_OP (normalOp)
-
-
- //==============================================================================
- #else
- #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
- for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
-
- #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
- for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
-
- #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
- for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
-
- #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
- for (auto i = (decltype (num)) 0; i < num; ++i) normalOp;
-
- #endif
-
- //==============================================================================
- #define JUCE_VEC_LOOP(vecOp, srcLoad, dstLoad, dstStore, locals, increment) \
- for (auto i = (decltype (numLongOps)) 0; i < numLongOps; ++i) \
- { \
- locals (srcLoad, dstLoad); \
- dstStore (dest, vecOp); \
- increment; \
- }
-
- #define JUCE_VEC_LOOP_TWO_SOURCES(vecOp, src1Load, src2Load, dstStore, locals, increment) \
- for (auto i = (decltype (numLongOps)) 0; i < numLongOps; ++i) \
- { \
- locals (src1Load, src2Load); \
- dstStore (dest, vecOp); \
- increment; \
- }
-
- #define JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD(vecOp, src1Load, src2Load, dstLoad, dstStore, locals, increment) \
- for (auto i = (decltype (numLongOps)) 0; i < numLongOps; ++i) \
- { \
- locals (src1Load, src2Load, dstLoad); \
- dstStore (dest, vecOp); \
- increment; \
- }
-
- #define JUCE_LOAD_NONE(srcLoad, dstLoad)
- #define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest);
- #define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src);
- #define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load) const Mode::ParallelType s1 = src1Load (src1), s2 = src2Load (src2);
- #define JUCE_LOAD_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad) const Mode::ParallelType d = dstLoad (dest), s1 = src1Load (src1), s2 = src2Load (src2);
- #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
-
- union signMask32 { float f; uint32 i; };
- union signMask64 { double d; uint64 i; };
-
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- template <int typeSize> struct ModeType { using Mode = BasicOps32; };
- template <> struct ModeType<8> { using Mode = BasicOps64; };
-
- template <typename Mode>
- struct MinMax
- {
- using Type = typename Mode::Type;
- using ParallelType = typename Mode::ParallelType;
-
- template <typename Size>
- static Type findMinOrMax (const Type* src, Size num, const bool isMinimum) noexcept
- {
- auto numLongOps = num / Mode::numParallel;
-
- if (numLongOps > 1)
- {
- ParallelType val;
-
- #if ! JUCE_USE_ARM_NEON
- if (isAligned (src))
- {
- val = Mode::loadA (src);
-
- if (isMinimum)
- {
- while (--numLongOps > 0)
- {
- src += Mode::numParallel;
- val = Mode::min (val, Mode::loadA (src));
- }
- }
- else
- {
- while (--numLongOps > 0)
- {
- src += Mode::numParallel;
- val = Mode::max (val, Mode::loadA (src));
- }
- }
- }
- else
- #endif
- {
- val = Mode::loadU (src);
-
- if (isMinimum)
- {
- while (--numLongOps > 0)
- {
- src += Mode::numParallel;
- val = Mode::min (val, Mode::loadU (src));
- }
- }
- else
- {
- while (--numLongOps > 0)
- {
- src += Mode::numParallel;
- val = Mode::max (val, Mode::loadU (src));
- }
- }
- }
-
- Type result = isMinimum ? Mode::min (val)
- : Mode::max (val);
-
- num &= (Mode::numParallel - 1);
- src += Mode::numParallel;
-
- for (auto i = (decltype (num)) 0; i < num; ++i)
- result = isMinimum ? jmin (result, src[i])
- : jmax (result, src[i]);
-
- return result;
- }
-
- if (num <= 0)
- return 0;
-
- return isMinimum ? *std::min_element (src, src + num)
- : *std::max_element (src, src + num);
- }
-
- template <typename Size>
- static Range<Type> findMinAndMax (const Type* src, Size num) noexcept
- {
- auto numLongOps = num / Mode::numParallel;
-
- if (numLongOps > 1)
- {
- ParallelType mn, mx;
-
- #if ! JUCE_USE_ARM_NEON
- if (isAligned (src))
- {
- mn = Mode::loadA (src);
- mx = mn;
-
- while (--numLongOps > 0)
- {
- src += Mode::numParallel;
- const ParallelType v = Mode::loadA (src);
- mn = Mode::min (mn, v);
- mx = Mode::max (mx, v);
- }
- }
- else
- #endif
- {
- mn = Mode::loadU (src);
- mx = mn;
-
- while (--numLongOps > 0)
- {
- src += Mode::numParallel;
- const ParallelType v = Mode::loadU (src);
- mn = Mode::min (mn, v);
- mx = Mode::max (mx, v);
- }
- }
-
- Range<Type> result (Mode::min (mn),
- Mode::max (mx));
-
- num &= (Mode::numParallel - 1);
- src += Mode::numParallel;
-
- for (auto i = (decltype (num)) 0; i < num; ++i)
- result = result.getUnionWith (src[i]);
-
- return result;
- }
-
- return Range<Type>::findMinAndMax (src, num);
- }
- };
- #endif
-
- //==============================================================================
- namespace
- {
- template <typename Size>
- void clear (float* dest, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vclr (dest, 1, (vDSP_Length) num);
- #else
- zeromem (dest, (size_t) num * sizeof (float));
- #endif
- }
-
- template <typename Size>
- void clear (double* dest, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vclrD (dest, 1, (vDSP_Length) num);
- #else
- zeromem (dest, (size_t) num * sizeof (double));
- #endif
- }
-
- template <typename Size>
- void fill (float* dest, float valueToFill, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vfill (&valueToFill, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_DEST (dest[i] = valueToFill,
- val,
- JUCE_LOAD_NONE,
- const Mode::ParallelType val = Mode::load1 (valueToFill);)
- #endif
- }
-
- template <typename Size>
- void fill (double* dest, double valueToFill, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vfillD (&valueToFill, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_DEST (dest[i] = valueToFill,
- val,
- JUCE_LOAD_NONE,
- const Mode::ParallelType val = Mode::load1 (valueToFill);)
- #endif
- }
-
- template <typename Size>
- void copyWithMultiply (float* dest, const float* src, float multiplier, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsmul (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
- Mode::mul (mult, s),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- template <typename Size>
- void copyWithMultiply (double* dest, const double* src, double multiplier, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsmulD (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
- Mode::mul (mult, s),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- template <typename Size>
- void add (float* dest, float amount, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsadd (dest, 1, &amount, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount,
- Mode::add (d, amountToAdd),
- JUCE_LOAD_DEST,
- const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
- #endif
- }
-
- template <typename Size>
- void add (double* dest, double amount, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount,
- Mode::add (d, amountToAdd),
- JUCE_LOAD_DEST,
- const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
- }
-
- template <typename Size>
- void add (float* dest, const float* src, float amount, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount,
- Mode::add (am, s),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType am = Mode::load1 (amount);)
- #endif
- }
-
- template <typename Size>
- void add (double* dest, const double* src, double amount, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount,
- Mode::add (am, s),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType am = Mode::load1 (amount);)
- #endif
- }
-
- template <typename Size>
- void add (float* dest, const float* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vadd (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i],
- Mode::add (d, s),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST, )
- #endif
- }
-
- template <typename Size>
- void add (double* dest, const double* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vaddD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i],
- Mode::add (d, s),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST, )
- #endif
- }
-
- template <typename Size>
- void add (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vadd (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i],
- Mode::add (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void add (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vaddD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i],
- Mode::add (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void subtract (float* dest, const float* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsub (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i],
- Mode::sub (d, s),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST, )
- #endif
- }
-
- template <typename Size>
- void subtract (double* dest, const double* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsubD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i],
- Mode::sub (d, s),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST, )
- #endif
- }
-
- template <typename Size>
- void subtract (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsub (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i],
- Mode::sub (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void subtract (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsubD (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i],
- Mode::sub (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void addWithMultiply (float* dest, const float* src, float multiplier, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsma (src, 1, &multiplier, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier,
- Mode::add (d, Mode::mul (mult, s)),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- template <typename Size>
- void addWithMultiply (double* dest, const double* src, double multiplier, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsmaD (src, 1, &multiplier, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier,
- Mode::add (d, Mode::mul (mult, s)),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- template <typename Size>
- void addWithMultiply (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vma ((float*) src1, 1, (float*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i],
- Mode::add (d, Mode::mul (s1, s2)),
- JUCE_LOAD_SRC1_SRC2_DEST,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void addWithMultiply (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmaD ((double*) src1, 1, (double*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i],
- Mode::add (d, Mode::mul (s1, s2)),
- JUCE_LOAD_SRC1_SRC2_DEST,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void subtractWithMultiply (float* dest, const float* src, float multiplier, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i] * multiplier,
- Mode::sub (d, Mode::mul (mult, s)),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- }
-
- template <typename Size>
- void subtractWithMultiply (double* dest, const double* src, double multiplier, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i] * multiplier,
- Mode::sub (d, Mode::mul (mult, s)),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- }
-
- template <typename Size>
- void subtractWithMultiply (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] -= src1[i] * src2[i],
- Mode::sub (d, Mode::mul (s1, s2)),
- JUCE_LOAD_SRC1_SRC2_DEST,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- }
-
- template <typename Size>
- void subtractWithMultiply (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] -= src1[i] * src2[i],
- Mode::sub (d, Mode::mul (s1, s2)),
- JUCE_LOAD_SRC1_SRC2_DEST,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- }
-
- template <typename Size>
- void multiply (float* dest, const float* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmul (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i],
- Mode::mul (d, s),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST, )
- #endif
- }
-
- template <typename Size>
- void multiply (double* dest, const double* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmulD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i],
- Mode::mul (d, s),
- JUCE_LOAD_SRC_DEST,
- JUCE_INCREMENT_SRC_DEST, )
- #endif
- }
-
- template <typename Size>
- void multiply (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmul (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i],
- Mode::mul (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void multiply (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmulD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i],
- Mode::mul (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void multiply (float* dest, float multiplier, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsmul (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier,
- Mode::mul (d, mult),
- JUCE_LOAD_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- template <typename Size>
- void multiply (double* dest, double multiplier, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vsmulD (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier,
- Mode::mul (d, mult),
- JUCE_LOAD_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- template <typename Size>
- void multiply (float* dest, const float* src, float multiplier, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
- Mode::mul (mult, s),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- }
-
- template <typename Size>
- void multiply (double* dest, const double* src, double multiplier, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier,
- Mode::mul (mult, s),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- }
-
- template <typename Size>
- void negate (float* dest, const float* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vneg ((float*) src, 1, dest, 1, (vDSP_Length) num);
- #else
- copyWithMultiply (dest, src, -1.0f, num);
- #endif
- }
-
- template <typename Size>
- void negate (double* dest, const double* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vnegD ((double*) src, 1, dest, 1, (vDSP_Length) num);
- #else
- copyWithMultiply (dest, src, -1.0f, num);
- #endif
- }
-
- template <typename Size>
- void abs (float* dest, const float* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vabs ((float*) src, 1, dest, 1, (vDSP_Length) num);
- #else
- FloatVectorHelpers::signMask32 signMask;
- signMask.i = 0x7fffffffUL;
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = std::abs (src[i]),
- Mode::bit_and (s, mask),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mask = Mode::load1 (signMask.f);)
-
- ignoreUnused (signMask);
- #endif
- }
-
- template <typename Size>
- void abs (double* dest, const double* src, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vabsD ((double*) src, 1, dest, 1, (vDSP_Length) num);
- #else
- FloatVectorHelpers::signMask64 signMask;
- signMask.i = 0x7fffffffffffffffULL;
-
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = std::abs (src[i]),
- Mode::bit_and (s, mask),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mask = Mode::load1 (signMask.d);)
-
- ignoreUnused (signMask);
- #endif
- }
-
- template <typename Size>
- void min (float* dest, const float* src, float comp, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp),
- Mode::min (s, cmp),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType cmp = Mode::load1 (comp);)
- }
-
- template <typename Size>
- void min (double* dest, const double* src, double comp, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp),
- Mode::min (s, cmp),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType cmp = Mode::load1 (comp);)
- }
-
- template <typename Size>
- void min (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmin ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]),
- Mode::min (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void min (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vminD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]),
- Mode::min (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void max (float* dest, const float* src, float comp, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp),
- Mode::max (s, cmp),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType cmp = Mode::load1 (comp);)
- }
-
- template <typename Size>
- void max (double* dest, const double* src, double comp, Size num) noexcept
- {
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp),
- Mode::max (s, cmp),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType cmp = Mode::load1 (comp);)
- }
-
- template <typename Size>
- void max (float* dest, const float* src1, const float* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmax ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]),
- Mode::max (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void max (double* dest, const double* src1, const double* src2, Size num) noexcept
- {
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vmaxD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]),
- Mode::max (s1, s2),
- JUCE_LOAD_SRC1_SRC2,
- JUCE_INCREMENT_SRC1_SRC2_DEST, )
- #endif
- }
-
- template <typename Size>
- void clip (float* dest, const float* src, float low, float high, Size num) noexcept
- {
- jassert (high >= low);
-
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vclip ((float*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low),
- Mode::max (Mode::min (s, hi), lo),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType lo = Mode::load1 (low);
- const Mode::ParallelType hi = Mode::load1 (high);)
- #endif
- }
-
- template <typename Size>
- void clip (double* dest, const double* src, double low, double high, Size num) noexcept
- {
- jassert (high >= low);
-
- #if JUCE_USE_VDSP_FRAMEWORK
- vDSP_vclipD ((double*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low),
- Mode::max (Mode::min (s, hi), lo),
- JUCE_LOAD_SRC,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType lo = Mode::load1 (low);
- const Mode::ParallelType hi = Mode::load1 (high);)
- #endif
- }
-
- template <typename Size>
- Range<float> findMinAndMax (const float* src, Size num) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinAndMax (src, num);
- #else
- return Range<float>::findMinAndMax (src, num);
- #endif
- }
-
- template <typename Size>
- Range<double> findMinAndMax (const double* src, Size num) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinAndMax (src, num);
- #else
- return Range<double>::findMinAndMax (src, num);
- #endif
- }
-
- template <typename Size>
- float findMinimum (const float* src, Size num) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinOrMax (src, num, true);
- #else
- return juce::findMinimum (src, num);
- #endif
- }
-
- template <typename Size>
- double findMinimum (const double* src, Size num) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinOrMax (src, num, true);
- #else
- return juce::findMinimum (src, num);
- #endif
- }
-
- template <typename Size>
- float findMaximum (const float* src, Size num) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps32>::findMinOrMax (src, num, false);
- #else
- return juce::findMaximum (src, num);
- #endif
- }
-
- template <typename Size>
- double findMaximum (const double* src, Size num) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
- return FloatVectorHelpers::MinMax<FloatVectorHelpers::BasicOps64>::findMinOrMax (src, num, false);
- #else
- return juce::findMaximum (src, num);
- #endif
- }
-
- template <typename Size>
- void convertFixedToFloat (float* dest, const int* src, float multiplier, Size num) noexcept
- {
- #if JUCE_USE_ARM_NEON
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = (float) src[i] * multiplier,
- vmulq_n_f32 (vcvtq_f32_s32 (vld1q_s32 (src)), multiplier),
- JUCE_LOAD_NONE,
- JUCE_INCREMENT_SRC_DEST, )
- #else
- JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = (float) src[i] * multiplier,
- Mode::mul (mult, _mm_cvtepi32_ps (_mm_loadu_si128 (reinterpret_cast<const __m128i*> (src)))),
- JUCE_LOAD_NONE,
- JUCE_INCREMENT_SRC_DEST,
- const Mode::ParallelType mult = Mode::load1 (multiplier);)
- #endif
- }
-
- } // namespace
- } // namespace FloatVectorHelpers
-
- //==============================================================================
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::clear (FloatType* dest,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::clear (dest, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::fill (FloatType* dest,
- FloatType valueToFill,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::fill (dest, valueToFill, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::copy (FloatType* dest,
- const FloatType* src,
- CountType numValues) noexcept
- {
- memcpy (dest, src, (size_t) numValues * sizeof (FloatType));
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::copyWithMultiply (FloatType* dest,
- const FloatType* src,
- FloatType multiplier,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::copyWithMultiply (dest, src, multiplier, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::add (FloatType* dest,
- FloatType amountToAdd,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::add (dest, amountToAdd, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::add (FloatType* dest,
- const FloatType* src,
- FloatType amount,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::add (dest, src, amount, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::add (FloatType* dest,
- const FloatType* src,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::add (dest, src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::add (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType num) noexcept
- {
- FloatVectorHelpers::add (dest, src1, src2, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::subtract (FloatType* dest,
- const FloatType* src,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::subtract (dest, src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::subtract (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType num) noexcept
- {
- FloatVectorHelpers::subtract (dest, src1, src2, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::addWithMultiply (FloatType* dest,
- const FloatType* src,
- FloatType multiplier,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::addWithMultiply (dest, src, multiplier, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::addWithMultiply (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType num) noexcept
- {
- FloatVectorHelpers::addWithMultiply (dest, src1, src2, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::subtractWithMultiply (FloatType* dest,
- const FloatType* src,
- FloatType multiplier,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::subtractWithMultiply (dest, src, multiplier, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::subtractWithMultiply (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType num) noexcept
- {
- FloatVectorHelpers::subtractWithMultiply (dest, src1, src2, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::multiply (FloatType* dest,
- const FloatType* src,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::multiply (dest, src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::multiply (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::multiply (dest, src1, src2, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::multiply (FloatType* dest,
- FloatType multiplier,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::multiply (dest, multiplier, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::multiply (FloatType* dest,
- const FloatType* src,
- FloatType multiplier,
- CountType num) noexcept
- {
- FloatVectorHelpers::multiply (dest, src, multiplier, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::negate (FloatType* dest,
- const FloatType* src,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::negate (dest, src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::abs (FloatType* dest,
- const FloatType* src,
- CountType numValues) noexcept
- {
- FloatVectorHelpers::abs (dest, src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::min (FloatType* dest,
- const FloatType* src,
- FloatType comp,
- CountType num) noexcept
- {
- FloatVectorHelpers::min (dest, src, comp, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::min (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType num) noexcept
- {
- FloatVectorHelpers::min (dest, src1, src2, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::max (FloatType* dest,
- const FloatType* src,
- FloatType comp,
- CountType num) noexcept
- {
- FloatVectorHelpers::max (dest, src, comp, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::max (FloatType* dest,
- const FloatType* src1,
- const FloatType* src2,
- CountType num) noexcept
- {
- FloatVectorHelpers::max (dest, src1, src2, num);
- }
-
- template <typename FloatType, typename CountType>
- void JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::clip (FloatType* dest,
- const FloatType* src,
- FloatType low,
- FloatType high,
- CountType num) noexcept
- {
- FloatVectorHelpers::clip (dest, src, low, high, num);
- }
-
- template <typename FloatType, typename CountType>
- Range<FloatType> JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::findMinAndMax (const FloatType* src,
- CountType numValues) noexcept
- {
- return FloatVectorHelpers::findMinAndMax (src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- FloatType JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::findMinimum (const FloatType* src,
- CountType numValues) noexcept
- {
- return FloatVectorHelpers::findMinimum (src, numValues);
- }
-
- template <typename FloatType, typename CountType>
- FloatType JUCE_CALLTYPE FloatVectorOperationsBase<FloatType, CountType>::findMaximum (const FloatType* src,
- CountType numValues) noexcept
- {
- return FloatVectorHelpers::findMaximum (src, numValues);
- }
-
- template struct FloatVectorOperationsBase<float, int>;
- template struct FloatVectorOperationsBase<float, size_t>;
- template struct FloatVectorOperationsBase<double, int>;
- template struct FloatVectorOperationsBase<double, size_t>;
-
- void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, size_t num) noexcept
- {
- FloatVectorHelpers::convertFixedToFloat (dest, src, multiplier, num);
- }
-
- void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
- {
- FloatVectorHelpers::convertFixedToFloat (dest, src, multiplier, num);
- }
-
- intptr_t JUCE_CALLTYPE FloatVectorOperations::getFpStatusRegister() noexcept
- {
- intptr_t fpsr = 0;
- #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS
- fpsr = static_cast<intptr_t> (_mm_getcsr());
- #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON
- #if defined(__arm64__) || defined(__aarch64__)
- asm volatile("mrs %0, fpcr"
- : "=r"(fpsr));
- #elif JUCE_USE_ARM_NEON
- asm volatile("vmrs %0, fpscr"
- : "=r"(fpsr));
- #endif
- #else
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
- jassertfalse; // No support for getting the floating point status register for your platform
- #endif
- #endif
-
- return fpsr;
- }
-
- void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) noexcept
- {
- #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS
- // the volatile keyword here is needed to workaround a bug in AppleClang 13.0
- // which aggressively optimises away the variable otherwise
- volatile auto fpsr_w = static_cast<uint32_t> (fpsr);
- _mm_setcsr (fpsr_w);
- #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON
- #if defined(__arm64__) || defined(__aarch64__)
- asm volatile("msr fpcr, %0"
- :
- : "ri"(fpsr));
- #elif JUCE_USE_ARM_NEON
- asm volatile("vmsr fpscr, %0"
- :
- : "ri"(fpsr));
- #endif
- #else
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
- jassertfalse; // No support for getting the floating point status register for your platform
- #endif
- ignoreUnused (fpsr);
- #endif
- }
-
- void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
- #if JUCE_USE_SSE_INTRINSICS
- intptr_t mask = _MM_FLUSH_ZERO_MASK;
- #else /*JUCE_USE_ARM_NEON*/
- intptr_t mask = (1 << 24 /* FZ */);
- #endif
- setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0));
- #else
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
- jassertfalse; // No support for flush to zero mode on your platform
- #endif
- ignoreUnused (shouldEnable);
- #endif
- }
-
- void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool shouldDisable) noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
- #if JUCE_USE_SSE_INTRINSICS
- intptr_t mask = 0x8040;
- #else /*JUCE_USE_ARM_NEON*/
- intptr_t mask = (1 << 24 /* FZ */);
- #endif
-
- setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldDisable ? mask : 0));
- #else
- ignoreUnused (shouldDisable);
-
- #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))
- jassertfalse; // No support for disable denormals mode on your platform
- #endif
- #endif
- }
-
- bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
- #if JUCE_USE_SSE_INTRINSICS
- intptr_t mask = 0x8040;
- #else /*JUCE_USE_ARM_NEON*/
- intptr_t mask = (1 << 24 /* FZ */);
- #endif
-
- return ((getFpStatusRegister() & mask) == mask);
- #else
- return false;
- #endif
- }
-
- ScopedNoDenormals::ScopedNoDenormals() noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
- #if JUCE_USE_SSE_INTRINSICS
- intptr_t mask = 0x8040;
- #else /*JUCE_USE_ARM_NEON*/
- intptr_t mask = (1 << 24 /* FZ */);
- #endif
-
- fpsr = FloatVectorOperations::getFpStatusRegister();
- FloatVectorOperations::setFpStatusRegister (fpsr | mask);
- #endif
- }
-
- ScopedNoDenormals::~ScopedNoDenormals() noexcept
- {
- #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))
- FloatVectorOperations::setFpStatusRegister (fpsr);
- #endif
- }
-
-
- //==============================================================================
- //==============================================================================
- #if JUCE_UNIT_TESTS
-
- class FloatVectorOperationsTests : public UnitTest
- {
- public:
- FloatVectorOperationsTests()
- : UnitTest ("FloatVectorOperations", UnitTestCategories::audio)
- {}
-
- template <typename ValueType>
- struct TestRunner
- {
- static void runTest (UnitTest& u, Random random)
- {
- const int range = random.nextBool() ? 500 : 10;
- const int num = random.nextInt (range) + 1;
-
- HeapBlock<ValueType> buffer1 (num + 16), buffer2 (num + 16);
- HeapBlock<int> buffer3 (num + 16, true);
-
- #if JUCE_ARM
- ValueType* const data1 = buffer1;
- ValueType* const data2 = buffer2;
- int* const int1 = buffer3;
- #else
- // These tests deliberately operate on misaligned memory and will be flagged up by
- // checks for undefined behavior!
- ValueType* const data1 = addBytesToPointer (buffer1.get(), random.nextInt (16));
- ValueType* const data2 = addBytesToPointer (buffer2.get(), random.nextInt (16));
- int* const int1 = addBytesToPointer (buffer3.get(), random.nextInt (16));
- #endif
-
- fillRandomly (random, data1, num);
- fillRandomly (random, data2, num);
-
- Range<ValueType> minMax1 (FloatVectorOperations::findMinAndMax (data1, num));
- Range<ValueType> minMax2 (Range<ValueType>::findMinAndMax (data1, num));
- u.expect (minMax1 == minMax2);
-
- u.expect (valuesMatch (FloatVectorOperations::findMinimum (data1, num), juce::findMinimum (data1, num)));
- u.expect (valuesMatch (FloatVectorOperations::findMaximum (data1, num), juce::findMaximum (data1, num)));
-
- u.expect (valuesMatch (FloatVectorOperations::findMinimum (data2, num), juce::findMinimum (data2, num)));
- u.expect (valuesMatch (FloatVectorOperations::findMaximum (data2, num), juce::findMaximum (data2, num)));
-
- FloatVectorOperations::clear (data1, num);
- u.expect (areAllValuesEqual (data1, num, 0));
-
- FloatVectorOperations::fill (data1, (ValueType) 2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 2));
-
- FloatVectorOperations::add (data1, (ValueType) 2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 4));
-
- FloatVectorOperations::copy (data2, data1, num);
- u.expect (areAllValuesEqual (data2, num, (ValueType) 4));
-
- FloatVectorOperations::add (data2, data1, num);
- u.expect (areAllValuesEqual (data2, num, (ValueType) 8));
-
- FloatVectorOperations::copyWithMultiply (data2, data1, (ValueType) 4, num);
- u.expect (areAllValuesEqual (data2, num, (ValueType) 16));
-
- FloatVectorOperations::addWithMultiply (data2, data1, (ValueType) 4, num);
- u.expect (areAllValuesEqual (data2, num, (ValueType) 32));
-
- FloatVectorOperations::multiply (data1, (ValueType) 2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
-
- FloatVectorOperations::multiply (data1, data2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 256));
-
- FloatVectorOperations::negate (data2, data1, num);
- u.expect (areAllValuesEqual (data2, num, (ValueType) -256));
-
- FloatVectorOperations::subtract (data1, data2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 512));
-
- FloatVectorOperations::abs (data1, data2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 256));
-
- FloatVectorOperations::abs (data2, data1, num);
- u.expect (areAllValuesEqual (data2, num, (ValueType) 256));
-
- fillRandomly (random, int1, num);
- doConversionTest (u, data1, data2, int1, num);
-
- FloatVectorOperations::fill (data1, (ValueType) 2, num);
- FloatVectorOperations::fill (data2, (ValueType) 3, num);
- FloatVectorOperations::addWithMultiply (data1, data1, data2, num);
- u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
- }
-
- static void doConversionTest (UnitTest& u, float* data1, float* data2, int* const int1, int num)
- {
- FloatVectorOperations::convertFixedToFloat (data1, int1, 2.0f, num);
- convertFixed (data2, int1, 2.0f, num);
- u.expect (buffersMatch (data1, data2, num));
- }
-
- static void doConversionTest (UnitTest&, double*, double*, int*, int) {}
-
- static void fillRandomly (Random& random, ValueType* d, int num)
- {
- while (--num >= 0)
- *d++ = (ValueType) (random.nextDouble() * 1000.0);
- }
-
- static void fillRandomly (Random& random, int* d, int num)
- {
- while (--num >= 0)
- *d++ = random.nextInt();
- }
-
- static void convertFixed (float* d, const int* s, ValueType multiplier, int num)
- {
- while (--num >= 0)
- *d++ = (float) *s++ * multiplier;
- }
-
- static bool areAllValuesEqual (const ValueType* d, int num, ValueType target)
- {
- while (--num >= 0)
- if (*d++ != target)
- return false;
-
- return true;
- }
-
- static bool buffersMatch (const ValueType* d1, const ValueType* d2, int num)
- {
- while (--num >= 0)
- if (! valuesMatch (*d1++, *d2++))
- return false;
-
- return true;
- }
-
- static bool valuesMatch (ValueType v1, ValueType v2)
- {
- return std::abs (v1 - v2) < std::numeric_limits<ValueType>::epsilon();
- }
- };
-
- void runTest() override
- {
- beginTest ("FloatVectorOperations");
-
- for (int i = 1000; --i >= 0;)
- {
- TestRunner<float>::runTest (*this, getRandom());
- TestRunner<double>::runTest (*this, getRandom());
- }
- }
- };
-
- static FloatVectorOperationsTests vectorOpTests;
-
- #endif
-
- } // namespace juce
|