Skip to content

Instantly share code, notes, and snippets.

@butchi
Last active July 24, 2024 14:01
Show Gist options
  • Save butchi/a1a72f560f4acb920f12cb7f2dcd20c9 to your computer and use it in GitHub Desktop.
Save butchi/a1a72f560f4acb920f12cb7f2dcd20c9 to your computer and use it in GitHub Desktop.
演算子オーバーライドをせず加算と乗算ができる複素整数型(JavaScript版とC言語版をそれぞれ簡易実装)
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}`
)
}
}
}
}
}
#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