Last active
July 24, 2024 14:01
-
-
Save butchi/a1a72f560f4acb920f12cb7f2dcd20c9 to your computer and use it in GitHub Desktop.
演算子オーバーライドをせず加算と乗算ができる複素整数型(JavaScript版とC言語版をそれぞれ簡易実装)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class IntComplex8 { | |
// // IntComplex3 | |
// static bit = 3 | |
// static i = 2 ** IntComplex8.bit // => 8 | |
// static modulo = IntComplex8.i ** 2 + 1 // => 65 | |
// static omega = 2 ** (IntComplex8.bit * 2 - 1) - 2 ** (IntComplex8.bit - 1) // => 28 | |
// // IntComplex4 | |
// static bit = 4 | |
// static i = 2 ** IntComplex8.bit // => 16 | |
// static modulo = IntComplex8.i ** 2 + 1 // => 257 | |
// static omega = 2 ** (IntComplex8.bit * 2 - 1) - 2 ** (IntComplex8.bit - 1) // => 120 | |
static bit = 8 | |
static i = 2 ** IntComplex8.bit // => 256 | |
static modulo = IntComplex8.i ** 2 + 1 // => 65537 | |
static omega = 2 ** (IntComplex8.bit * 2 - 1) - 2 ** (IntComplex8.bit - 1) // => 32640 | |
constructor(x, y) { | |
this.val = IntComplex8.vecToNum([x, y]) | |
} | |
get re() { | |
return IntComplex8.numToVec(this.val)[0] | |
} | |
get im() { | |
return IntComplex8.numToVec(this.val)[1] | |
} | |
static vecToNum([x, y]) { | |
return (x + y * IntComplex8.i + IntComplex8.modulo) % IntComplex8.modulo | |
} | |
static numToVec(n) { | |
const geta = IntComplex8.modulo | |
const nGeta = n < this.omega ? n + geta : n | |
const xRaw = (nGeta - 1) % IntComplex8.i | |
const yRaw = Math.floor((nGeta - 1 + IntComplex8.i / 2) / this.i) | |
const x = xRaw >= IntComplex8.i / 2 ? xRaw - IntComplex8.i : xRaw | |
const y = yRaw - IntComplex8.i | |
return [x, y] | |
} | |
static from(n) { | |
return new IntComplex8(...IntComplex8.numToVec(n % IntComplex8.modulo)) | |
} | |
valueOf() { | |
return this.val | |
} | |
toString() { | |
const [re, im] = [this.re, this.im] | |
if (im === 0) { | |
return `${re}` | |
} else if (im > 0) { | |
if (im === 1) { | |
if (re === 0) { | |
return "i" | |
} else { | |
return `${re} + i` | |
} | |
} else { | |
if (re === 0) { | |
return `${im} i` | |
} else { | |
return `${re} + ${im} i` | |
} | |
} | |
} else if (im < 0) { | |
if (im === -1) { | |
if (re === 0) { | |
return "-i" | |
} else { | |
return `${re} - i` | |
} | |
} else { | |
if (re === 0) { | |
return `-${Math.abs(im)} i` | |
} else { | |
return `${re} - ${Math.abs(im)} i` | |
} | |
} | |
} | |
} | |
} | |
// test | |
for (let y2 = -8; y2 < 8; y2++) { | |
for (let x2 = -8; x2 < 8; x2++) { | |
for (let y1 = -8; y1 < 8; y1++) { | |
for (let x1 = -8; x1 < 8; x1++) { | |
const c1 = new IntComplex8(x1, y1) | |
const c2 = new IntComplex8(x2, y2) | |
const c = IntComplex8.from(c1 + c2) | |
if ( | |
c.re !== c1.re + c2.re || | |
c.im !== c1.im + c2.im | |
) { | |
console.log( | |
`(${c1}) + (${c2}) = ${c}` | |
) | |
} | |
} | |
} | |
} | |
} | |
// Incorrect: (-8 - 8 i) * (-8 - 8 i) => -1 - 128 i | |
for (let y2 = -8; y2 < 8; y2++) { | |
for (let x2 = -8; x2 < 8; x2++) { | |
for (let y1 = -8; y1 < 8; y1++) { | |
for (let x1 = -8; x1 < 8; x1++) { | |
const c1 = new IntComplex8(x1, y1) | |
const c2 = new IntComplex8(x2, y2) | |
const c = IntComplex8.from(c1 * c2) | |
if ( | |
c.re !== c1.re * c2.re - c1.im * c2.im || | |
c.im !== c1.re * c2.im + c1.im * c2.re | |
) { | |
console.log( | |
`Error: (${c1}) * (${c2}) => ${c}` | |
) | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#define BIT 16 | |
long I; | |
long MODULO; | |
long OMEGA; | |
unsigned long compToNum(short x, short y) { | |
unsigned long n = (x + y * I + MODULO) % MODULO; | |
return n; | |
} | |
short numToRe(unsigned long nRaw) { | |
unsigned long n = nRaw % MODULO; | |
// if (n == OMEGA) { | |
// return; | |
// } | |
unsigned long geta = MODULO; | |
unsigned long nGeta = (n < OMEGA) ? (n + geta) : n; | |
short reRaw = (nGeta - 1) % I; | |
short re = (reRaw >= (I / 2)) ? (reRaw - I) : reRaw; | |
return re; | |
} | |
short numToIm(unsigned long nRaw) { | |
unsigned long n = nRaw % MODULO; | |
// if (n == OMEGA) { | |
// return; | |
// } | |
unsigned long geta = MODULO; | |
unsigned long nGeta = (n < OMEGA) ? (n + geta) : n; | |
short imRaw = ((nGeta - 1 + I / 2) >> BIT); | |
short im = imRaw - I; | |
return im; | |
} | |
int main(void) { | |
I = 1 << BIT; | |
MODULO = I * I + 1; | |
OMEGA = (1 << (BIT * 2 - 1)) - (1 << (BIT - 1)); | |
unsigned long c1; | |
unsigned long c2; | |
unsigned long c; | |
short re1 = 3; | |
short im1 = 3; | |
short re2 = 0; | |
short im2 = 5; | |
c1 = compToNum(re1, im1); | |
c2 = compToNum(re2, im2); | |
c = c1 * c2; | |
short re = numToRe(c); | |
short im = numToIm(c); | |
printf("BIT: %d\n", BIT); | |
printf("I: %ld\n", I); | |
printf("MODULO: %ld\n", MODULO); | |
printf("OMEGA: %ld\n", OMEGA); | |
printf("c1: %ld: (%d, %d)\n", c1, numToRe(c1), numToIm(c1)); | |
printf("c2: %ld: (%d, %d)\n", c2, numToRe(c2), numToIm(c2)); | |
printf("c1 * c2: %ld: (%d, %d)", c, re, im); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment