C ++での循環シフト(回転)操作のベストプラクティス


93

左および右シフト演算子(<<および>>)は、C ++ですでに使用可能です。しかし、循環シフトまたは回転操作を実行する方法を見つけることができませんでした。

「左回転」「右回転」などの操作はどのように行うのですか?

ここで2回右に回転

Initial --> 1000 0011 0100 0010

結果として:

Final   --> 1010 0000 1101 0000

例が参考になります。

(編集者注:Cで回転を表現する多くの一般的な方法は、回転カウントがゼロの場合、または単一の回転機械命令以上にコンパイルされる場合、未定義の動作の影響を受けます。この質問の回答は、ベストプラクティスを文書化する必要があります。)



回答:


104

別の回転質問この回答の以前のバージョンも参照してくださいasm gcc / clangがx86用に生成するものについての詳細を含む。

未定義の動作を回避するCおよびC ++で回転を表現する最もコンパイラーに適した方法は、John Regehrの実装のようです。タイプの幅に応じて回転するように調整しました(などの固定幅タイプを使用uint32_t)。

#include <stdint.h>   // for uint32_t
#include <limits.h>   // for CHAR_BIT
// #define NDEBUG
#include <assert.h>

static inline uint32_t rotl32 (uint32_t n, unsigned int c)
{
  const unsigned int mask = (CHAR_BIT*sizeof(n) - 1);  // assumes width is a power of 2.

  // assert ( (c<=mask) &&"rotate by type width or more");
  c &= mask;
  return (n<<c) | (n>>( (-c)&mask ));
}

static inline uint32_t rotr32 (uint32_t n, unsigned int c)
{
  const unsigned int mask = (CHAR_BIT*sizeof(n) - 1);

  // assert ( (c<=mask) &&"rotate by type width or more");
  c &= mask;
  return (n>>c) | (n<<( (-c)&mask ));
}

だけuint32_tでなく、任意の符号なし整数型で機能するため、他のサイズのバージョンを作成できます。

多くの安全チェック(タイプ幅が2の累乗であることを含む)を備えたC ++ 11テンプレートバージョンも参照してくださいstatic_assert。これは、一部の24ビットDSPまたは36ビットメインフレームには当てはまりません。

回転幅を明示的に含む名前のラッパーのバックエンドとしてのみテンプレートを使用することをお勧めします。 整数昇格ルールは、rotl_template(u16 & 0x11UL, 7)16ではなく32または64ビットローテーションを実行することを意味します(幅に応じてunsigned long)。でもuint16_t & uint16_tに昇格されるsigned intプラットフォームを除いて、C ++の整数プロモーションルールによってintより広いnoですuint16_t


x86では、このバージョンは、コンパイラーがx86の回転およびシフト命令を認識しているため、それを処理するコンパイラーを使用して単一rol r32, cl(またはrol r32, imm8)にインライン化します。がCソースと同じ方法でシフトカウントをマスクです。

用のx86上でこのUB-回避イディオムのためのコンパイラのサポート、uint32_t xおよびunsigned int n可変数のシフトのために:

  • clang:clang3.5以降、可変カウントローテーションで認識され、その前に複数のシフト+またはインス
  • gcc:gcc4.9以降、変数カウントローテーションで認識され、その前に複数のシフト+またはinsns。gcc5以降では、変数カウントのroror rol命令のみを使用して、ウィキペディアバージョンのブランチとマスクも最適化します。
  • icc:ICC13以前から変数カウントローテーションでサポートされています。BMI2がMOVの保存に使用できない場合、定数カウントローテーションshld edi,edi,7rol edi,7、一部のCPU(特にAMD、一部のIntel)に比べて低速で多くのバイトを使用しますrorx eax,edi,25
  • MSVC:x86-64 CL19:定数カウントローテーションでのみ認識されます。(ウィキペディアのイディオムは認識されていますが、ブランチとANDは最適化されていません)。x86(x86-64を含む)の_rotl/ _rotr組み込み関数を使用し<intrin.h>ます。

ARMのgccはand r1, r1, #31for変数カウント循環を使用しますが、実際の回転は単一の命令で実行しますror r0, r0, r1。そのため、gccは、回転カウントが本質的にモジュール式であることを認識していません。ARMのドキュメントにあるように、「シフト長nが32を超えるRORは、シフト長が指定されたRORと同じですn-32。ARMでの左/右シフトがカウントを飽和させるため、gccはここで混乱すると思います。32以上シフトするとレジスタがクリアされます。(x86とは異なり、シフトはカウントを回転と同じようにマスクします)。回転イディオムを認識する前にAND命令が必要であると判断するのは、そのターゲットで非循環シフトがどのように機能するかによります。

現在のx86コンパイラは、8および16ビットローテートの変数カウントをマスクするために追加の命令をまだ使用しています。これは、おそらくARMでのANDを回避しないのと同じ理由によります。パフォーマンスはどのx86-64 CPUの回転数にも依存しないため、これは最適化されていません。(カウントのマスキングは、シフトを反復的に処理するため、パフォーマンス上の理由から286で導入されました。最新のCPUのような一定のレイテンシではありません。)

ところで、回転数32-nだけを提供するARMやMIPSのようなアーキテクチャでコンパイラが左回転を実装するのを避けるために、変数カウントの回転では回転右を優先します。(これは、コンパイル時定数のカウントにより最適化されます。)

おもしろい事実:ARMには実際には専用のシフト/回転命令がありません。これは、RORモードでソースオペランドがバレルシフターを通過する MOV ですmov r0, r0, ror r1。したがって、回転は、EOR命令などのレジスタソースオペランドに折りたたむことができます。


に符号なしの型nと戻り値を使用してくださいそうしないと、ローテートにはなりません。(x86ターゲットのgccは算術右シフトを実行し、ゼロではなく符号ビットのコピーをシフトインするORため、2つの値を一緒にシフトすると問題が発生します。負の符号付き整数の右シフトは、Cの実装定義の動作です。)

また、シフトカウントが符号なしの型であることを確認してくださいであること(-n)&31をで 1の補数または符号/大きさであり、符号なしまたは2の補数で得られるモジュラー2 ^ nと同じではない場合があります。(Regehrのブログ投稿のコメントを参照してください)。 unsigned int私が調べたすべてのコンパイラで、すべての幅でうまく機能しxます。他のいくつかの型は、一部のコンパイラのイディオム認識を無効にするため、と同じ型を使用しないでくださいx


一部のコンパイラーは、対象のコンパイラーでポータブルバージョンが適切なコードを生成しない場合、inline-asmよりもはるかに優れたrotatesの組み込み関数を提供します。私が知っているコンパイラには、クロスプラットフォームの組み込み関数はありません。これらは、x86オプションの一部です。

  • および組み込み<immintrin.h>提供する_rotl_rotl64インテルのドキュメント。右シフトについても同様です。MSVCにはが必要ですが<intrin.h>、gccには<x86intrin.h>。アンは#ifdef、GCC対ICCの世話をするが、打ち鳴らすはどこでもそれらを提供していないようですでMSVC互換モード以外で-fms-extensions -fms-compatibility -fms-compatibility-version=17.00。そして、彼らが吸うasmは吸う(追加のマスキングとCMOV)。
  • MSVC: _rotr8および_rotr16
  • GCCおよびICC(ない打ち鳴らす) <x86intrin.h>も提供__rolb/ __rorb8ビットの回転のためには、右/左__rolw/ __rorw(16ビット) __rold/ __rord(32ビット)__rolq/ __rorq(のみ64ビットのターゲットに対して定義された64ビット)。狭い回転の場合、実装では__builtin_ia32_rolhiorを使用します...qiが、32ビットおよび64ビットの回転は、shift / orを使用して定義されます(コードはia32intrin.hx86のgcc でのみ機能するため、UBに対する保護はありません)。GNU Cには、クロスプラットフォームの__builtin_rotate機能がありません__builtin_popcount(単一の命令でなくても、ターゲットプラットフォームで最適なものに拡張されます)。ほとんどの場合、イディオム認識から優れたコードを取得します。

// For real use, probably use a rotate intrinsic for MSVC, or this idiom for other compilers.  This pattern of #ifdefs may be helpful
#if defined(__x86_64__) || defined(__i386__)

#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>  // Not just <immintrin.h> for compilers other than icc
#endif

uint32_t rotl32_x86_intrinsic(rotwidth_t x, unsigned n) {
  //return __builtin_ia32_rorhi(x, 7);  // 16-bit rotate, GNU C
  return _rotl(x, n);  // gcc, icc, msvc.  Intel-defined.
  //return __rold(x, n);  // gcc, icc.
  // can't find anything for clang
}
#endif

おそらく一部の非x86コンパイラーにも組み込み関数がありますが、このコミュニティーWikiの回答を拡張してそれらすべてを含めることはできません。(多分、組み込みについての既存の答えでそれをするでしょう)。


(この回答の古いバージョンでは、MSVC固有のインラインasm(32ビットx86コードでのみ機能))、またはhttp://www.devx.com/tips/Tip/14043が推奨されていました Cバージョンのがました。コメントへの返信。)

インラインasmは入力を強制的に格納/再ロードするため特にMSVCスタイルの多くの最適化無効にします。丁寧に書かれたGNU C inline-asm rotateは、カウントをコンパイル時定数シフトカウントの直接のオペランドにすることを可能にしますが、シフトされる値もコンパイル時定数である場合、完全に最適化できませんでした。インライン化後。 https://gcc.gnu.org/wiki/DontUseInlineAsm


1
好奇心が強い、なぜそうではないbits = CHAR_BIT * sizeof(n);c &= bits - 1;そしてreturn ((n >> c) | (n << (bits - c)))、そして私は何を使うのでしょうか?
mirabilos 2015

@mirabilos:あなたのバージョンは、= 32ビットでUBを持っている、のシフトで、= 32カウントbits - c= 32 - 0。(私はwikiを編集しただけで、そもそもpingを受け取りませんでした。そもそもwikiを記述していないためです。)
Peter Cordes

@PeterCordes 0 < count < bitsは、ローテーションを実装するほとんどすべてのCPUおよびプログラミング言語の一定の要件です(0 ≤ count < bitsただし、ビットの正確な量によるシフトは実質的に常に定義されていないか、値をクリアして回転するのではなく、nopに切り捨てられます)。
mirabilos 2017

@mirabilos:そうですが、私たちの目標は、シフトカウントを単一のasm命令に直接送る関数を書くことですが、可能なシフトカウントについてはCレベルでUBを回避します。Cには回転演算子または関数がないので、このイディオムのコンポーネント部分でUBを避けたいと思います。コンパイラがCシフトを処理するターゲットのasmシフト命令と同じ方法で処理することに依存するのではなく、(そして、BTW、ARMはレジスタ幅を超える変数カウントシフトでレジスタをゼロにし、レジ​​スタの最下位バイトからカウントを取得します。回答にリンクします。)
Peter Cordes

1
私は「ポータブルスニペットを使用する」と言いましたが、コードをチェックしたところ、(a)シフトカウントゼロの UBが呼び出され、(b)MSVCで組み込み関数のみが使用されているようです。一般に、すべてのコンパイラおよびプラットフォーム固有のハックで機能するもののコンパイル可能な「参照コード」としてそれを使用するのは良い考えのようです...
BeeOnRope

33

C ++なので、インライン関数を使用します。

template <typename INT> 
INT rol(INT val) {
    return (val << 1) | (val >> (sizeof(INT)*CHAR_BIT-1));
}

C ++ 11バリアント:

template <typename INT> 
constexpr INT rol(INT val) {
    static_assert(std::is_unsigned<INT>::value,
                  "Rotate Left only makes sense for unsigned types");
    return (val << 1) | (val >> (sizeof(INT)*CHAR_BIT-1));
}

5
警告:が符号INT付き整数であり、符号が設定されている場合、このコードは無効です!たとえばrol<std::int32_t>(1 << 31)、1に反転する必要があるが実際には-1(符号が保持されるため)テストする。
誰も

9
@Nobody:5年前に、符号付き整数型を使用しないでくださいとコメントしました。いずれにしても、回転は符号付き整数型では意味がありません。
MSalters

2
std::numeric_limits<INT>::digits代わりに使用できますCHAR_BIT * sizeof。符号なしの型に未使用のパディング(たとえば、32ビットに格納された24ビットの整数)を許可するかどうかは忘れますが、許可する場合はそのdigits方が適しています。可変カウントシフトのチェックを強化したバージョンについては、gist.github.com / pabigot / 7550454も参照してください。
Peter Cordes 2017年

1
@PeterCordes:そうです。私はクレイがやったと思います(指数フィールドがパディングされる浮動小数点レジスターを使用しました)。
MSalters 2017年

1
@ fake-name '>そのため、C ++ 11バージョンは、何か他のものに変更しない限り、Windowsでは機能しません...'ええ、それをLinuxに変更します。:)
スラバ

20

ほとんどのコンパイラにはそのための組み込み関数があります。たとえばVisual Studio _rotr8、_rotr16)


うわー!受け入れられた答えよりもはるかに簡単です。ところで、DWORD(32ビット)の場合は、_rotrおよび_rotlを使用します。
Gabe Halsmer、

15

決定的に:

template<class T>
T ror(T x, unsigned int moves)
{
  return (x >> moves) | (x << sizeof(T)*8 - moves);
}

6
これは8スペルミスCHAR_BITですか(正確に8である必要はありません)?
Toby Speight 2017年

2
これは私の答えと同じです(ただし、右から左に入れ替える場合を除く)std::numeric_limits<T>::digits。私の答えに関するPeter Cordesのコメントもここで適用されます:use 。
MSalters

14

C ++ 20 std::rotlおよびstd::rotr

入荷しました!http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.htmlそれを<bit>ヘッダーに追加する必要があります

cppreferenceによると、使用方法は次のようになります。

#include <bit>
#include <bitset>
#include <cstdint>
#include <iostream>

int main()
{
    std::uint8_t i = 0b00011101;
    std::cout << "i          = " << std::bitset<8>(i) << '\n';
    std::cout << "rotl(i,0)  = " << std::bitset<8>(std::rotl(i,0)) << '\n';
    std::cout << "rotl(i,1)  = " << std::bitset<8>(std::rotl(i,1)) << '\n';
    std::cout << "rotl(i,4)  = " << std::bitset<8>(std::rotl(i,4)) << '\n';
    std::cout << "rotl(i,9)  = " << std::bitset<8>(std::rotl(i,9)) << '\n';
    std::cout << "rotl(i,-1) = " << std::bitset<8>(std::rotl(i,-1)) << '\n';
}

出力を与える:

i          = 00011101
rotl(i,0)  = 00011101
rotl(i,1)  = 00111010
rotl(i,4)  = 11010001
rotl(i,9)  = 00111010
rotl(i,-1) = 10001110

サポートがGCCに届いたら、試してみます。GCC9.1.0はg++-9 -std=c++2aまだサポートしていません。

提案は言う:

ヘッダ:

namespace std {
  // 25.5.5, rotating   
  template<class T>
    [[nodiscard]] constexpr T rotl(T x, int s) noexcept;
  template<class T>
    [[nodiscard]] constexpr T rotr(T x, int s) noexcept;

そして:

25.5.5回転[bitops.rot]

以下の説明では、Nはを示しstd::numeric_limits<T>::digitsます。

template<class T>
  [[nodiscard]] constexpr T rotl(T x, int s) noexcept;

制約:Tは符号なし整数型です(3.9.1 [basic.fundamental])。

rをs%Nとします。

戻り値:rが0の場合、x。rが正の場合(x << r) | (x >> (N - r))、rが負の場合、rotr(x, -r)

template<class T>
  [[nodiscard]] constexpr T rotr(T x, int s) noexcept;

制約:Tは符号なし整数型です(3.9.1 [basic.fundamental])。rをs%Nとします。

戻り値:rが0の場合、x。rが正の場合(x >> r) | (x << (N - r))、rが負の場合、rotl(x, -r)

std::popcount1ビットの数をカウントするためにA も追加されました。32ビット整数の設定ビット数をカウントする方法は?


最新のC ++にビットローテーションが表示されるまでに、どうして長い時間がかかりましたか?LLVM clangでも、ほんの数年前に組み込み関数があっただけです=> review.llvm.org/D21457 ARMは2010年より前にローテーションを行っていたので、c ++ 11以降はそこにあるはずです。
サンソーン

7

標準ビットセットを使用して、このようなものをどのように...

#include <bitset> 
#include <iostream> 

template <std::size_t N> 
inline void 
rotate(std::bitset<N>& b, unsigned m) 
{ 
   b = b << m | b >> (N-m); 
} 

int main() 
{ 
   std::bitset<8> b(15); 
   std::cout << b << '\n'; 
   rotate(b, 2); 
   std::cout << b << '\n'; 

   return 0;
}

HTH、


ビットセットの長さよりも大きいシフトに対応するように変更する必要があります。
H.グリーン

m %= N;シフトを考慮して追加されました>= N
ミラニア

7

xが8ビット値の場合、これを使用できます。

x=(x>>1 | x<<7);

2
x署名されている場合、おそらく正しく動作しません。
sam hocevar 2017

6

詳細には、次のロジックを適用できます。

整数のビットパターンが33602の場合

1000 0011 0100 0010

次に、2つの右シフトを使用してロールオーバーする必要があります。最初にビットパターンのコピーを作成し、次に左シフトします。

14回左シフトした後、あなたは得ます。

1000 0000 0000 0000

次に、値33602を必要に応じて2回右シフトします。あなたが得る

0010 0000 1101 0000

次に、左にシフトした値の14倍と右にシフトした値の2倍の間のORを取ります。

1000 0000 0000 0000
0010 0000 1101 0000
===================
1010 0000 1101 0000
===================

そして、シフトされたロールオーバー値を取得します。ビット単位の操作はより高速であり、ループを必要としないことを忘れないでください。


1
上記のサブルーチンに似ています... b = b << m | b >>(Nm);
SMカムラン

それはORではなくXORであるべきではありませんか?1 ^ 0 = 1、^ 0 = 0、などそれはだか、排他的ではない場合、これは常に1になるだろう
BK

5

Lビット単位で右にシフトしたいとし、入力xNビットのある数値であると仮定します。

unsigned ror(unsigned x, int L, int N) 
{
    unsigned lsbs = x & ((1 << L) - 1);
    return (x >> L) | (lsbs << (N-L));
}

3

正解は次のとおりです。

#define BitsCount( val ) ( sizeof( val ) * CHAR_BIT )
#define Shift( val, steps ) ( steps % BitsCount( val ) )
#define ROL( val, steps ) ( ( val << Shift( val, steps ) ) | ( val >> ( BitsCount( val ) - Shift( val, steps ) ) ) )
#define ROR( val, steps ) ( ( val >> Shift( val, steps ) ) | ( val << ( BitsCount( val ) - Shift( val, steps ) ) ) )

val署名されている場合、おそらく正しく動作しません。
sam hocevar 2017

0

ソースコードxビット数

int x =8;
data =15; //input
unsigned char tmp;
for(int i =0;i<x;i++)
{
printf("Data & 1    %d\n",data&1);
printf("Data Shifted value %d\n",data>>1^(data&1)<<(x-1));
tmp = data>>1|(data&1)<<(x-1);
data = tmp;  
}

0

別の提案

template<class T>
inline T rotl(T x, unsigned char moves){
    unsigned char temp;
    __asm{
        mov temp, CL
        mov CL, moves
        rol x, CL
        mov CL, temp
    };
    return x;
}

0

以下は、両方向が実装されたDídacPérezの回答のわずかに改善されたバージョンと、unsigned charおよびunsigned long long値を使用したこれらの関数の使用法のデモです。いくつかのメモ:

  1. 関数はコンパイラー最適化のためにインライン化されます
  2. cout << +valueはここで見つけた符号なし文字を数値で簡潔に出力するためのトリックを使用しました:https : //stackoverflow.com/a/28414758/1599699
  3. <put the type here>明確さと安全のために、明示的な構文を使用することをお勧めします。
  4. ここの「追加の詳細」セクション見つけたため、shiftNumパラメータにunsigned charを使用しました。

加法式が負の場合、または加法式が(昇格された)シフト式のビット数以上の場合、シフト演算の結果は未定義です。

これが私が使っているコードです:

#include <iostream>

using namespace std;

template <typename T>
inline T rotateAndCarryLeft(T rotateMe, unsigned char shiftNum)
{
    static const unsigned char TBitCount = sizeof(T) * 8U;

    return (rotateMe << shiftNum) | (rotateMe >> (TBitCount - shiftNum));
}

template <typename T>
inline T rotateAndCarryRight(T rotateMe, unsigned char shiftNum)
{
    static const unsigned char TBitCount = sizeof(T) * 8U;

    return (rotateMe >> shiftNum) | (rotateMe << (TBitCount - shiftNum));
}

void main()
{
    //00010100 == (unsigned char)20U
    //00000101 == (unsigned char)5U == rotateAndCarryLeft(20U, 6U)
    //01010000 == (unsigned char)80U == rotateAndCarryRight(20U, 6U)

    cout << "unsigned char " << 20U << " rotated left by 6 bits == " << +rotateAndCarryLeft<unsigned char>(20U, 6U) << "\n";
    cout << "unsigned char " << 20U << " rotated right by 6 bits == " << +rotateAndCarryRight<unsigned char>(20U, 6U) << "\n";

    cout << "\n";


    for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned char) * 8U; ++shiftNum)
    {
        cout << "unsigned char " << 21U << " rotated left by " << +shiftNum << " bit(s) == " << +rotateAndCarryLeft<unsigned char>(21U, shiftNum) << "\n";
    }

    cout << "\n";

    for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned char) * 8U; ++shiftNum)
    {
        cout << "unsigned char " << 21U << " rotated right by " << +shiftNum << " bit(s) == " << +rotateAndCarryRight<unsigned char>(21U, shiftNum) << "\n";
    }


    cout << "\n";

    for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned long long) * 8U; ++shiftNum)
    {
        cout << "unsigned long long " << 3457347ULL << " rotated left by " << +shiftNum << " bit(s) == " << rotateAndCarryLeft<unsigned long long>(3457347ULL, shiftNum) << "\n";
    }

    cout << "\n";

    for (unsigned char shiftNum = 0U; shiftNum <= sizeof(unsigned long long) * 8U; ++shiftNum)
    {
        cout << "unsigned long long " << 3457347ULL << " rotated right by " << +shiftNum << " bit(s) == " << rotateAndCarryRight<unsigned long long>(3457347ULL, shiftNum) << "\n";
    }

    cout << "\n\n";
    system("pause");
}

0
--- Substituting RLC in 8051 C for speed --- Rotate left carry
Here is an example using RLC to update a serial 8 bit DAC msb first:
                               (r=DACVAL, P1.4= SDO, P1.5= SCLK)
MOV     A, r
?1:
MOV     B, #8
RLC     A
MOV     P1.4, C
CLR     P1.5
SETB    P1.5
DJNZ    B, ?1

Here is the code in 8051 C at its fastest:
sbit ACC_7  = ACC ^ 7 ; //define this at the top to access bit 7 of ACC
ACC     =   r;
B       =   8;  
do  {
P1_4    =   ACC_7;  // this assembles into mov c, acc.7  mov P1.4, c 
ACC     <<= 1;
P1_5    =   0;
P1_5    =   1;
B       --  ; 
    } while ( B!=0 );
The keil compiler will use DJNZ when a loop is written this way.
I am cheating here by using registers ACC and B in c code.
If you cannot cheat then substitute with:
P1_4    =   ( r & 128 ) ? 1 : 0 ;
r     <<=   1;
This only takes a few extra instructions.
Also, changing B for a local var char n is the same.
Keil does rotate ACC left by ADD A, ACC which is the same as multiply 2.
It only takes one extra opcode i think.
Keeping code entirely in C keeps things simpler sometimes.

-1

関数をオーバーロードします。

unsigned int rotate_right(unsigned int x)
{
 return (x>>1 | (x&1?0x80000000:0))
}

unsigned short rotate_right(unsigned short x) { /* etc. */ }

-1
#define ROTATE_RIGHT(x) ( (x>>1) | (x&1?0x8000:0) )

マクロへの引数として式を使用した厄介な驚きを避けるために、xを括弧で囲む必要があります。
ジョーイ

3
値が16ビットでない場合、黙ってナンセンスになります
ジェームズホプキン

マクロとして定義する場合は、副作用として式を引数として渡さないように注意する必要があります。
Phil Miller
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.